1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
|
= Package Architecture Specific =
The Package-Architecture-Specific (PAS) module is a parser to a set
of restrictions to build packages based on archive-admin experiences.
Those restrictions overlap the metadata information from the source
packages (architecturehintlist).
For testing PAS we will create a set of publications using
`SoyuzTestPublisher`.
>>> from lp.registry.interfaces.distribution import (
... IDistributionSet)
>>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
>>> hoary = ubuntu.getSeries('hoary')
>>> from lp.soyuz.tests.test_publishing import (
... SoyuzTestPublisher)
>>> from lp.testing.layers import LaunchpadZopelessLayer
Publication will be added as 'launchpad' DB user.
>>> LaunchpadZopelessLayer.switchDbUser("launchpad")
>>> test_publisher = SoyuzTestPublisher()
>>> ignore = test_publisher.setUpDefaultDistroSeries(hoary)
>>> test_publisher.addFakeChroots()
>>> pub_three = test_publisher.getPubSource(
... sourcename='test-buildd-3', version='669',
... architecturehintlist="i386 hppa amd64")
Create a PPA source publication.
>>> from lp.registry.interfaces.person import IPersonSet
>>> cprov = getUtility(IPersonSet).getByName('cprov')
>>> pub_ppa = test_publisher.getPubSource(
... sourcename='test-ppa', version='675',
... architecturehintlist="i386 hppa",
... archive=cprov.archive)
Good, all done, we can commit the publications and continue the tests
with the buildmaster DB user.
>>> from lp.services.database.sqlbase import commit
>>> commit()
>>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
== Check the architectures to build ==
Hoary has only 'hppa' and 'i386' architectures.
>>> legal_archs = set(hoary.architectures)
>>> def print_architectures(architectures):
... arch_tags = [arch.architecturetag for arch in architectures]
... for tag in sorted(arch_tags):
... print tag
>>> print_architectures(legal_archs)
hppa
i386
See if the code which determines archs to build does the right thing for
each of these options:
>>> from lp.soyuz.pas import (
... BuildDaemonPackagesArchSpecific, determineArchitecturesToBuild)
>>> def print_build_architectures(pub, pas_verify=None):
... allowed_architectures = determineArchitecturesToBuild(
... pub, legal_archs, hoary, pas_verify)
... print_architectures(allowed_architectures)
=== Source PAS ===
Source PAS lines are the ones starting with '%' followed by the source
package name, colon and then a list of architecture tags separated by
space.
Create a harness that lets us easily test PAS statements:
>>> import os
>>> import tempfile
>>> import shutil
>>> def getPASVerifier(pas_string):
... """Build and return a PAS verifier based on the string provided."""
... temp_dir = tempfile.mkdtemp()
... pas_filename = os.path.join(temp_dir, "Packages-arch-specific")
... pas_file = open(pas_filename, "w")
... pas_file.write(pas_string)
... pas_file.close()
... pas_verify = BuildDaemonPackagesArchSpecific(temp_dir, hoary)
... shutil.rmtree(temp_dir)
... return pas_verify
Normally, 'pub_three' would be built on all available architectures in
hoary.
>>> print_build_architectures(pub_three)
hppa
i386
But it it can be 'temporarily' restricted to build only on 'i386' via
PAS.
>>> pas_verify = getPASVerifier("%test-buildd-3: i386")
>>> print_build_architectures(pub_three, pas_verify)
i386
Or even restricted to not be built in any architecture.
>>> pas_verify = getPASVerifier("%test-buildd-3: sparc")
>>> print_build_architectures(pub_three, pas_verify)
PAS can also be used for excluding specific architectures.
>>> pas_verify = getPASVerifier("%test-buildd-3: !i386")
>>> print_build_architectures(pub_three, pas_verify)
hppa
PPA builds are not affected by PAS restrictions, i.e., they will
build for all requested architectures currently supported in the PPA
subsystem.
>>> pas_verify = getPASVerifier("%test-ppa: hppa")
>>> print_build_architectures(pub_ppa, pas_verify)
i386
>>> pas_verify = getPASVerifier("%test-ppa: !i386")
>>> print_build_architectures(pub_ppa, pas_verify)
i386
== Binary PAS ==
Binary PAS lines are the ones which does not start with '%'. They
contain binary package name, colon and then a list of architecture
tags separated by space.
Binary PAS lines work as a shortcut to the source when they produce
only a single binary. When the binary mentioned is part of a
collection of binaries produced by the same source the architecture
restriction does not make sense anymore. See more information about
this aspect below.
To check binary PAS listings we'll use a source publication for which
produces a single binary.
>>> from lp.soyuz.enums import (
... PackagePublishingStatus)
>>> LaunchpadZopelessLayer.switchDbUser("launchpad")
>>> pub_single = test_publisher.getPubSource(
... sourcename='single', version='1.0',
... architecturehintlist="any")
>>> binaries = test_publisher.getPubBinaries(
... binaryname='single-bin', pub_source=pub_single,
... status=PackagePublishingStatus.PUBLISHED)
>>> commit()
>>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
>>> len(set(pub.binarypackagerelease.name
... for pub in pub_single.getPublishedBinaries()))
1
Normally the source would be built in all the available architectures
in hoary.
>>> print_build_architectures(pub_single)
hppa
i386
The source building does not get affect by an unrelated binary PAS line.
>>> pas_verify = getPASVerifier("boing: i386")
>>> print_build_architectures(pub_single, pas_verify)
hppa
i386
Using PAS, we can restrict the building architectures by tagging the
produced binary with a specific list of allowed architectures.
>>> pas_verify = getPASVerifier("single-bin: i386 sparc")
>>> print_build_architectures(pub_single, pas_verify)
i386
It's also possible to only block specific architectures.
>>> pas_verify = getPASVerifier("single-bin: !hppa")
>>> print_build_architectures(pub_single, pas_verify)
i386
Although it's not possible to block the build on the
'nominatedarchindep' architecture via a binary PAS line. The reason
for that is the fact the architecture independent binaries are only
built in i386, if it gets blacklisted those binaries won't be
built. This would never be a legitimate use-case.
>>> pas_verify = getPASVerifier("single-bin: !i386 !hppa")
>>> print_build_architectures(pub_single, pas_verify)
i386
Binary PAS lines are ignored for PPAs as well. We create a binary for
the existing test PPA source publication.
>>> LaunchpadZopelessLayer.switchDbUser("launchpad")
>>> pub_ppa.archive.require_virtualized = False
>>> binaries = test_publisher.getPubBinaries(
... binaryname='ppa-bin', pub_source=pub_ppa,
... status=PackagePublishingStatus.PUBLISHED)
>>> commit()
>>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
And it will build in the same architectures with or without a
corresponding PAS binary line.
>>> print_build_architectures(pub_ppa)
hppa
i386
>>> pas_verify = getPASVerifier("ppa-bin: !hppa")
>>> print_build_architectures(pub_single, pas_verify)
hppa
i386
As mentioned above, PAS binary lines referring to binary packages for
which the source produce other binaries are completely ignored. Other
tools use that information but we can't restrict builds in this
circumstances.
We will create a 'multiple' source publication build two binaries,
'bin-one' and 'bin-two'.
>>> LaunchpadZopelessLayer.switchDbUser("launchpad")
>>> pub_multiple = test_publisher.getPubSource(
... sourcename='multiple', version='1.1',
... architecturehintlist="any")
>>> for build in pub_multiple.createMissingBuilds():
... bin_one = test_publisher.uploadBinaryForBuild(
... build, 'bin-one')
... pub_bin_one = test_publisher.publishBinaryInArchive(
... bin_one, pub_multiple.archive,
... status=PackagePublishingStatus.PUBLISHED)
... bin_two = test_publisher.uploadBinaryForBuild(
... build, 'bin-two')
... pub_bin_two = test_publisher.publishBinaryInArchive(
... bin_two, pub_multiple.archive,
... status=PackagePublishingStatus.PUBLISHED)
>>> commit()
>>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
>>> len(set(pub.binarypackagerelease.name
... for pub in pub_multiple.getPublishedBinaries()))
2
Any attempt to restrict the building architectures on 'multiple'
source via its binaries will be ignored and it will continue to be
built for all available architectures.
>>> print_build_architectures(pub_multiple)
hppa
i386
>>> pas_verify = getPASVerifier("bin-one: i386 sparc")
>>> print_build_architectures(pub_multiple, pas_verify)
hppa
i386
>>> pas_verify = getPASVerifier("bin-two: !hppa")
>>> print_build_architectures(pub_multiple, pas_verify)
hppa
i386
|