Merge lp:~apw/launchpad/signing-reinstate-raw-uefi-custom-upload into lp:launchpad

Proposed by Andy Whitcroft on 2016-05-26
Status: Merged
Merged at revision: 18080
Proposed branch: lp:~apw/launchpad/signing-reinstate-raw-uefi-custom-upload
Merge into: lp:launchpad
Diff against target: 415 lines (+165/-46)
9 files modified
lib/lp/archivepublisher/configure.zcml (+7/-0)
lib/lp/archivepublisher/signing.py (+22/-2)
lib/lp/archivepublisher/tests/test_signing.py (+66/-32)
lib/lp/archiveuploader/nascentuploadfile.py (+8/-3)
lib/lp/soyuz/browser/queue.py (+1/-0)
lib/lp/soyuz/enums.py (+7/-1)
lib/lp/soyuz/model/queue.py (+5/-2)
lib/lp/soyuz/scripts/custom_uploads_copier.py (+7/-2)
lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py (+42/-4)
To merge this branch: bzr merge lp:~apw/launchpad/signing-reinstate-raw-uefi-custom-upload
Reviewer Review Type Date Requested Status
Colin Watson 2016-05-26 Approve on 2016-05-31
Review via email: mp+295848@code.launchpad.net

Commit message

Reinstate the raw-uefi custom upload as a distinct type.

Description of the change

Reinstate the raw-uefi custom upload as a distinct type. This utilises the same machinery as raw-signing. The only difference is the location in dists, with raw-uefi landing in dists/*/uefi and raw-signing landing in dists/*/signing.

To post a comment you must log in.
Colin Watson (cjwatson) :
review: Approve
Andy Whitcroft (apw) wrote :

Changes as requested pushed to the branch. Thanks for your reviews.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/archivepublisher/configure.zcml'
2--- lib/lp/archivepublisher/configure.zcml 2016-05-23 10:46:55 +0000
3+++ lib/lp/archivepublisher/configure.zcml 2016-05-31 12:46:39 +0000
4@@ -88,6 +88,13 @@
5 interface="lp.soyuz.interfaces.queue.ICustomUploadHandler"/>
6 </securedutility>
7 <securedutility
8+ class="lp.archivepublisher.signing.UefiUpload"
9+ provides="lp.soyuz.interfaces.queue.ICustomUploadHandler"
10+ name="UEFI">
11+ <allow
12+ interface="lp.soyuz.interfaces.queue.ICustomUploadHandler"/>
13+ </securedutility>
14+ <securedutility
15 class="lp.archivepublisher.signing.SigningUpload"
16 provides="lp.soyuz.interfaces.queue.ICustomUploadHandler"
17 name="SIGNING">
18
19=== modified file 'lib/lp/archivepublisher/signing.py'
20--- lib/lp/archivepublisher/signing.py 2016-05-26 10:46:04 +0000
21+++ lib/lp/archivepublisher/signing.py 2016-05-31 12:46:39 +0000
22@@ -15,6 +15,7 @@
23
24 __all__ = [
25 "SigningUpload",
26+ "UefiUpload",
27 ]
28
29 import os
30@@ -63,6 +64,8 @@
31 """
32 custom_type = "signing"
33
34+ dists_directory = "signed"
35+
36 @staticmethod
37 def parsePath(tarfile_path):
38 tarfile_base = os.path.basename(tarfile_path)
39@@ -94,8 +97,8 @@
40
41 self.setComponents(tarfile_path)
42
43- dists_signed = os.path.join(
44- pubconf.archiveroot, "dists", suite, "main", "signed")
45+ dists_signed = os.path.join(pubconf.archiveroot, "dists",
46+ suite, "main", self.dists_directory)
47 self.targetdir = os.path.join(
48 dists_signed, "%s-%s" % (self.package, self.arch))
49 self.archiveroot = pubconf.archiveroot
50@@ -302,3 +305,20 @@
51
52 def shouldInstall(self, filename):
53 return filename.startswith("%s/" % self.version)
54+
55+
56+class UefiUpload(SigningUpload):
57+ """Legacy UEFI Signing custom upload.
58+
59+ Provides backwards compatibility UEFI signing uploads. Existing
60+ packages use the raw-uefi custom upload and expect the results
61+ to be published to dists/*/uefi. These are a functional subset of
62+ raw-signing custom uploads differing only in where they are published
63+ in the archive.
64+
65+ We expect to be able to remove this upload type once all existing
66+ packages are converted to the new form and location.
67+ """
68+ custom_type = "uefi"
69+
70+ dists_directory = "uefi"
71
72=== modified file 'lib/lp/archivepublisher/tests/test_signing.py'
73--- lib/lp/archivepublisher/tests/test_signing.py 2016-05-26 10:46:39 +0000
74+++ lib/lp/archivepublisher/tests/test_signing.py 2016-05-31 12:46:39 +0000
75@@ -15,7 +15,10 @@
76 CustomUploadAlreadyExists,
77 CustomUploadBadUmask,
78 )
79-from lp.archivepublisher.signing import SigningUpload
80+from lp.archivepublisher.signing import (
81+ SigningUpload,
82+ UefiUpload,
83+ )
84 from lp.services.osutils import write_file
85 from lp.services.tarfile_helpers import LaunchpadWriteTarFile
86 from lp.testing import TestCase
87@@ -98,10 +101,10 @@
88 self.signingautokey = True
89
90
91-class TestSigning(TestCase):
92+class TestSigningHelpers(TestCase):
93
94 def setUp(self):
95- super(TestSigning, self).setUp()
96+ super(TestSigningHelpers, self).setUp()
97 self.temp_dir = self.makeTemporaryDirectory()
98 self.signing_dir = self.makeTemporaryDirectory()
99 self.pubconf = FakeConfigPrimary(self.temp_dir, self.signing_dir)
100@@ -135,43 +138,42 @@
101 self.buffer = open(self.path, "wb")
102 self.archive = LaunchpadWriteTarFile(self.buffer)
103
104- def process_emulate(self):
105- self.archive.close()
106- self.buffer.close()
107- upload = SigningUpload()
108- # Under no circumstances is it safe to execute actual commands.
109- self.fake_call = FakeMethod(result=0)
110- upload.callLog = FakeMethodCallLog(upload=upload)
111- self.useFixture(MonkeyPatch("subprocess.call", self.fake_call))
112- upload.process(self.pubconf, self.path, self.suite)
113-
114- return upload
115-
116- def process(self):
117- self.archive.close()
118- self.buffer.close()
119- upload = SigningUpload()
120- upload.signUefi = FakeMethod()
121- upload.signKmod = FakeMethod()
122- # Under no circumstances is it safe to execute actual commands.
123- fake_call = FakeMethod(result=0)
124- self.useFixture(MonkeyPatch("subprocess.call", fake_call))
125- upload.process(self.pubconf, self.path, self.suite)
126- self.assertEqual(0, fake_call.call_count)
127-
128- return upload
129-
130 def getDistsPath(self):
131 return os.path.join(self.pubconf.archiveroot, "dists",
132 self.suite, "main")
133
134+
135+class TestSigning(TestSigningHelpers):
136+
137 def getSignedPath(self, loader_type, arch):
138 return os.path.join(self.getDistsPath(), "signed",
139 "%s-%s" % (loader_type, arch))
140
141- def getUefiPath(self, loader_type, arch):
142- return os.path.join(self.getDistsPath(), "uefi",
143- "%s-%s" % (loader_type, arch))
144+ def process_emulate(self):
145+ self.archive.close()
146+ self.buffer.close()
147+ upload = SigningUpload()
148+ # Under no circumstances is it safe to execute actual commands.
149+ self.fake_call = FakeMethod(result=0)
150+ upload.callLog = FakeMethodCallLog(upload=upload)
151+ self.useFixture(MonkeyPatch("subprocess.call", self.fake_call))
152+ upload.process(self.pubconf, self.path, self.suite)
153+
154+ return upload
155+
156+ def process(self):
157+ self.archive.close()
158+ self.buffer.close()
159+ upload = SigningUpload()
160+ upload.signUefi = FakeMethod()
161+ upload.signKmod = FakeMethod()
162+ # Under no circumstances is it safe to execute actual commands.
163+ fake_call = FakeMethod(result=0)
164+ self.useFixture(MonkeyPatch("subprocess.call", fake_call))
165+ upload.process(self.pubconf, self.path, self.suite)
166+ self.assertEqual(0, fake_call.call_count)
167+
168+ return upload
169
170 def test_archive_copy(self):
171 # If there is no key/cert configuration, processing succeeds but
172@@ -599,3 +601,35 @@
173 self.assertTrue(os.path.exists(self.kmod_x509))
174 self.assertEqual(stat.S_IMODE(os.stat(self.kmod_pem).st_mode), 0o600)
175 self.assertEqual(stat.S_IMODE(os.stat(self.kmod_x509).st_mode), 0o644)
176+
177+
178+class TestUefi(TestSigningHelpers):
179+
180+ def getSignedPath(self, loader_type, arch):
181+ return os.path.join(self.getDistsPath(), "uefi",
182+ "%s-%s" % (loader_type, arch))
183+
184+ def process(self):
185+ self.archive.close()
186+ self.buffer.close()
187+ upload = UefiUpload()
188+ upload.signUefi = FakeMethod()
189+ upload.signKmod = FakeMethod()
190+ # Under no circumstances is it safe to execute actual commands.
191+ fake_call = FakeMethod(result=0)
192+ self.useFixture(MonkeyPatch("subprocess.call", fake_call))
193+ upload.process(self.pubconf, self.path, self.suite)
194+ self.assertEqual(0, fake_call.call_count)
195+
196+ return upload
197+
198+ def test_installed(self):
199+ # Files in the tarball are installed correctly.
200+ self.setUpUefiKeys()
201+ self.openArchive("test", "1.0", "amd64")
202+ self.archive.add_file("1.0/empty.efi", "")
203+ self.process()
204+ self.assertTrue(os.path.isdir(os.path.join(
205+ self.getDistsPath(), "uefi")))
206+ self.assertTrue(os.path.exists(os.path.join(
207+ self.getSignedPath("test", "amd64"), "1.0", "empty.efi")))
208
209=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
210--- lib/lp/archiveuploader/nascentuploadfile.py 2016-05-06 09:16:30 +0000
211+++ lib/lp/archiveuploader/nascentuploadfile.py 2016-05-31 12:46:39 +0000
212@@ -33,7 +33,10 @@
213 from lp.archivepublisher.debian_installer import DebianInstallerUpload
214 from lp.archivepublisher.dist_upgrader import DistUpgraderUpload
215 from lp.archivepublisher.rosetta_translations import RosettaTranslationsUpload
216-from lp.archivepublisher.signing import SigningUpload
217+from lp.archivepublisher.signing import (
218+ SigningUpload,
219+ UefiUpload,
220+ )
221 from lp.archiveuploader.utils import (
222 determine_source_file_type,
223 prefix_multi_line_string,
224@@ -258,8 +261,8 @@
225 PackageUploadCustomFormat.STATIC_TRANSLATIONS,
226 'raw-meta-data':
227 PackageUploadCustomFormat.META_DATA,
228+ 'raw-uefi': PackageUploadCustomFormat.UEFI,
229 'raw-signing': PackageUploadCustomFormat.SIGNING,
230- 'raw-uefi': PackageUploadCustomFormat.SIGNING, # Compatibility
231 }
232
233 custom_handlers = {
234@@ -268,6 +271,7 @@
235 PackageUploadCustomFormat.DDTP_TARBALL: DdtpTarballUpload,
236 PackageUploadCustomFormat.ROSETTA_TRANSLATIONS:
237 RosettaTranslationsUpload,
238+ PackageUploadCustomFormat.UEFI: UefiUpload,
239 PackageUploadCustomFormat.SIGNING: SigningUpload,
240 }
241
242@@ -309,7 +313,8 @@
243 """Return whether this custom upload can be automatically approved."""
244 # Signing uploads will be signed, and must therefore be approved
245 # by a human.
246- if self.custom_type == PackageUploadCustomFormat.SIGNING:
247+ if self.custom_type in (PackageUploadCustomFormat.UEFI,
248+ PackageUploadCustomFormat.SIGNING):
249 return False
250 return True
251
252
253=== modified file 'lib/lp/soyuz/browser/queue.py'
254--- lib/lp/soyuz/browser/queue.py 2016-05-09 18:07:49 +0000
255+++ lib/lp/soyuz/browser/queue.py 2016-05-31 12:46:39 +0000
256@@ -574,6 +574,7 @@
257 (self.contains_installer, ("Installer", 'ubuntu-icon')),
258 (self.contains_upgrader, ("Upgrader", 'ubuntu-icon')),
259 (self.contains_ddtp, (ddtp, 'ubuntu-icon')),
260+ (self.contains_uefi, ("UEFI Objects for Signing", 'ubuntu-icon')),
261 (self.contains_signing, ("Objects for Signing", 'ubuntu-icon')),
262 ]
263 return [
264
265=== modified file 'lib/lp/soyuz/enums.py'
266--- lib/lp/soyuz/enums.py 2016-05-03 14:44:33 +0000
267+++ lib/lp/soyuz/enums.py 2016-05-31 12:46:39 +0000
268@@ -481,7 +481,13 @@
269 the Software Center.
270 """)
271
272- SIGNING = DBItem(6, """
273+ UEFI = DBItem(6, """
274+ uefi
275+
276+ A tarball containing EFI images to be signed.
277+ """)
278+
279+ SIGNING = DBItem(7, """
280 signing
281
282 A tarball containing images to be signed.
283
284=== modified file 'lib/lp/soyuz/model/queue.py'
285--- lib/lp/soyuz/model/queue.py 2016-05-23 11:18:16 +0000
286+++ lib/lp/soyuz/model/queue.py 2016-05-31 12:46:39 +0000
287@@ -654,12 +654,15 @@
288 return PackageUploadCustomFormat.DDTP_TARBALL in self._customFormats
289
290 @cachedproperty
291+ def contains_uefi(self):
292+ """See `IPackageUpload`."""
293+ return PackageUploadCustomFormat.UEFI in self._customFormats
294+
295+ @cachedproperty
296 def contains_signing(self):
297 """See `IPackageUpload`."""
298 return PackageUploadCustomFormat.SIGNING in self._customFormats
299
300- contains_uefi = contains_signing
301-
302 @property
303 def package_name(self):
304 """See `IPackageUpload`."""
305
306=== modified file 'lib/lp/soyuz/scripts/custom_uploads_copier.py'
307--- lib/lp/soyuz/scripts/custom_uploads_copier.py 2016-05-06 09:16:30 +0000
308+++ lib/lp/soyuz/scripts/custom_uploads_copier.py 2016-05-31 12:46:39 +0000
309@@ -18,7 +18,10 @@
310 from lp.archivepublisher.debian_installer import DebianInstallerUpload
311 from lp.archivepublisher.dist_upgrader import DistUpgraderUpload
312 from lp.archivepublisher.rosetta_translations import RosettaTranslationsUpload
313-from lp.archivepublisher.signing import SigningUpload
314+from lp.archivepublisher.signing import (
315+ SigningUpload,
316+ UefiUpload,
317+ )
318 from lp.registry.interfaces.pocket import PackagePublishingPocket
319 from lp.services.database.bulk import load_referencing
320 from lp.soyuz.enums import PackageUploadCustomFormat
321@@ -40,6 +43,7 @@
322 PackageUploadCustomFormat.DDTP_TARBALL: DdtpTarballUpload,
323 PackageUploadCustomFormat.ROSETTA_TRANSLATIONS:
324 RosettaTranslationsUpload,
325+ PackageUploadCustomFormat.UEFI: UefiUpload,
326 PackageUploadCustomFormat.SIGNING: SigningUpload,
327 }
328
329@@ -63,7 +67,8 @@
330 return True
331 # Signing uploads will be signed, and must therefore be approved
332 # by a human.
333- if custom.customformat == PackageUploadCustomFormat.SIGNING:
334+ if custom.customformat in (PackageUploadCustomFormat.UEFI,
335+ PackageUploadCustomFormat.SIGNING):
336 return False
337 return True
338
339
340=== modified file 'lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py'
341--- lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py 2016-05-06 09:16:30 +0000
342+++ lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py 2016-05-31 12:46:39 +0000
343@@ -409,7 +409,7 @@
344 self.assertEqual(PackageUploadStatus.ACCEPTED, copied_pu.status)
345
346 def test_copyUpload_unapproves_signing_from_different_archive(self):
347- # Copies of UEFI custom uploads to a primary archive are set to
348+ # Copies of signing custom uploads to a primary archive are set to
349 # UNAPPROVED, since they will normally end up being signed.
350 target_series = self.factory.makeDistroSeries()
351 archive = self.factory.makeArchive(
352@@ -422,22 +422,60 @@
353 self.assertEqual(PackageUploadStatus.UNAPPROVED, copied_pu.status)
354
355 def test_copyUpload_approves_signing_from_same_archive(self):
356+ # Copies of signing custom uploads within the same archive are
357+ # automatically accepted, since they have already been signed.
358+ original_upload = self.makeUpload(
359+ custom_type=PackageUploadCustomFormat.SIGNING)
360+ target_series = self.factory.makeDistroSeries()
361+ copier = CustomUploadsCopier(target_series)
362+ copied_pu = copier.copyUpload(original_upload).packageupload
363+ self.assertEqual(PackageUploadStatus.ACCEPTED, copied_pu.status)
364+
365+ def test_copyUpload_approves_signing_to_ppa(self):
366+ # Copies of signing custom uploads to a PPA are automatically accepted,
367+ # since PPAs have much more limited upload permissions than the main
368+ # archive, and in any case PPAs do not have an upload approval
369+ # workflow.
370+ original_upload = self.makeUpload(
371+ custom_type=PackageUploadCustomFormat.SIGNING)
372+ target_series = self.factory.makeDistroSeries()
373+ target_archive = self.factory.makeArchive(
374+ distribution=target_series.distribution)
375+ copier = CustomUploadsCopier(
376+ target_series, target_archive=target_archive)
377+ copied_pu = copier.copyUpload(original_upload).packageupload
378+ self.assertEqual(PackageUploadStatus.ACCEPTED, copied_pu.status)
379+
380+ def test_copyUpload_unapproves_uefi_from_different_archive(self):
381+ # Copies of UEFI custom uploads to a primary archive are set to
382+ # UNAPPROVED, since they will normally end up being signed.
383+ target_series = self.factory.makeDistroSeries()
384+ archive = self.factory.makeArchive(
385+ distribution=target_series.distribution)
386+ original_upload = self.makeUpload(
387+ archive=archive, custom_type=PackageUploadCustomFormat.UEFI)
388+ copier = CustomUploadsCopier(
389+ target_series, target_archive=target_series.main_archive)
390+ copied_pu = copier.copyUpload(original_upload).packageupload
391+ self.assertEqual(PackageUploadStatus.UNAPPROVED, copied_pu.status)
392+
393+ def test_copyUpload_approves_uefi_from_same_archive(self):
394 # Copies of UEFI custom uploads within the same archive are
395 # automatically accepted, since they have already been signed.
396 original_upload = self.makeUpload(
397- custom_type=PackageUploadCustomFormat.SIGNING)
398+ custom_type=PackageUploadCustomFormat.UEFI)
399 target_series = self.factory.makeDistroSeries()
400 copier = CustomUploadsCopier(target_series)
401 copied_pu = copier.copyUpload(original_upload).packageupload
402 self.assertEqual(PackageUploadStatus.ACCEPTED, copied_pu.status)
403
404- def test_copyUpload_approves_signing_to_ppa(self):
405+ def test_copyUpload_approves_uefi_to_ppa(self):
406 # Copies of UEFI custom uploads to a PPA are automatically accepted,
407 # since PPAs have much more limited upload permissions than the main
408 # archive, and in any case PPAs do not have an upload approval
409 # workflow.
410 original_upload = self.makeUpload(
411- custom_type=PackageUploadCustomFormat.SIGNING)
412+ custom_type=PackageUploadCustomFormat.UEFI)
413 target_series = self.factory.makeDistroSeries()
414 target_archive = self.factory.makeArchive(
415 distribution=target_series.distribution)