Merge ~mwhudson/ubuntu-cdimage:only-launchpad-builders into ubuntu-cdimage:main

Proposed by Michael Hudson-Doyle
Status: Work in progress
Proposed branch: ~mwhudson/ubuntu-cdimage:only-launchpad-builders
Merge into: ubuntu-cdimage:main
Diff against target: 1035 lines (+67/-744)
2 files modified
lib/cdimage/livefs.py (+54/-255)
lib/cdimage/tests/test_livefs.py (+13/-489)
Reviewer Review Type Date Requested Status
Ubuntu CD Image Team Pending
Review via email: mp+456037@code.launchpad.net

Commit message

remove support for non launchpad livefs builders

Description of the change

This currently fails tests. Trying to figure out how to usefully test e.g. live_item_paths makes my head hurt so I've stopped for now. I wonder if we can just switch to downloading all the artefacts produced by the livefs, which would clean up the code quite extremely...

To post a comment you must log in.

Unmerged commits

160bb63... by Michael Hudson-Doyle

a start on how this test might work

Failed
[FAILED] run-tests:0 (build)
[WAITING] lint:0 (build)
12 of 2 results
393fc48... by Michael Hudson-Doyle

test stuff

92c9bbe... by Michael Hudson-Doyle

remove tests for functions i just deleted

4cc1f8b... by Michael Hudson-Doyle

remove support for non-launchpad livefs builders

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/cdimage/livefs.py b/lib/cdimage/livefs.py
2index c912dc0..e701155 100644
3--- a/lib/cdimage/livefs.py
4+++ b/lib/cdimage/livefs.py
5@@ -23,7 +23,6 @@ from gzip import GzipFile
6 import io
7 import os
8 import re
9-import subprocess
10 from textwrap import dedent
11 import time
12 try:
13@@ -79,61 +78,6 @@ def split_arch(config, arch):
14 return cpuarch, subarch
15
16
17-def live_builder(config, arch):
18- cpuarch, subarch = split_arch(config, arch)
19- project = config.project
20-
21- path = os.path.join(config.root, "production", "livefs-builders")
22- if os.path.exists(path):
23- with open(path) as f:
24- for line in f:
25- line = line.strip()
26- if not line or line.startswith("#"):
27- continue
28- try:
29- f_project, f_series, f_arch, builder = line.split(None, 3)
30- except ValueError:
31- continue
32- if not fnmatch.fnmatchcase(project, f_project):
33- continue
34- if not config.match_series(f_series):
35- continue
36- if "+" in f_arch:
37- want_arch = arch
38- else:
39- want_arch = cpuarch
40- if not fnmatch.fnmatchcase(want_arch, f_arch):
41- continue
42- return builder
43-
44- raise UnknownArchitecture("No live filesystem builder known for %s" % arch)
45-
46-
47-def live_build_options(config, arch):
48- options = []
49-
50- cpuarch, subarch = split_arch(config, arch)
51- if (cpuarch in ("armel", "armhf") and
52- config.image_type == "daily-preinstalled"):
53- if subarch in ("mx5", "omap", "omap4"):
54- options.extend(["-f", "ext4"])
55- elif subarch in ("ac100", "nexus7"):
56- options.extend(["-f", "plain"])
57-
58- if config.project in ("ubuntu-base", "ubuntu-core", "ubuntu-touch"):
59- options.extend(["-f", "plain"])
60-
61- if config.subproject == "wubi":
62- if config["DIST"] >= "trusty":
63- # TODO: Turn this back on once Wubi's resize2fs supports it.
64- # options.extend(["-f", "ext4"])
65- options.extend(["-f", "ext3"])
66- else:
67- options.extend(["-f", "ext3"])
68-
69- return options
70-
71-
72 def live_project(config, arch):
73 liveproject = config.livefs_project_for_arch(arch)
74
75@@ -144,37 +88,6 @@ def live_project(config, arch):
76 return liveproject
77
78
79-def live_build_command(config, arch):
80- command = [
81- "ssh", "-n", "-o", "StrictHostKeyChecking=no", "-o", "BatchMode=yes",
82- "buildd@%s" % live_builder(config, arch),
83- "/home/buildd/bin/BuildLiveCD",
84- ]
85-
86- if config["UBUNTU_DEFAULTS_LOCALE"]:
87- command.extend(["-u", config["UBUNTU_DEFAULTS_LOCALE"]])
88- command.append("-l")
89-
90- command.extend(live_build_options(config, arch))
91-
92- cpuarch, subarch = split_arch(config, arch)
93- if cpuarch:
94- command.extend(["-A", cpuarch])
95- if subarch:
96- command.extend(["-s", subarch])
97-
98- if config.get("PROPOSED", "0") not in ("", "0"):
99- command.append("-p")
100- if config.series:
101- command.extend(["-d", config.series])
102-
103- if config.subproject:
104- command.extend(["-r", config.subproject])
105- command.append(live_project(config, arch))
106-
107- return command
108-
109-
110 def live_build_lp_kwargs(config, lp, lp_livefs, arch):
111 cpuarch, subarch = split_arch(config, arch)
112 kwargs = {}
113@@ -222,8 +135,6 @@ def live_build_lp_kwargs(config, lp, lp_livefs, arch):
114 return kwargs
115
116
117-# TODO: This is only used for logging, so it might be worth unifying with
118-# live_build_notify_failure.
119 def live_build_full_name(config, arch):
120 bits = [config.project]
121 if config.subproject:
122@@ -235,7 +146,7 @@ def live_build_full_name(config, arch):
123 return "-".join(bits)
124
125
126-def live_build_notify_failure(config, arch, lp_build=None):
127+def live_build_notify_failure(config, arch, lp_build):
128 if config["DEBUG"]:
129 return
130
131@@ -256,19 +167,13 @@ def live_build_notify_failure(config, arch, lp_build=None):
132
133 datestamp = time.strftime("%Y%m%d")
134 try:
135- if lp_build is not None:
136- if lp_build.build_log_url is None:
137- raise URLError(
138- "Failed build %s has no build_log_url" % lp_build.web_link)
139- with closing(urlopen(lp_build.build_log_url, timeout=30)) as comp:
140- with closing(io.BytesIO(comp.read())) as comp_bytes:
141- with closing(GzipFile(fileobj=comp_bytes)) as f:
142- body = f.read()
143- else:
144- log_url = "http://%s/~buildd/LiveCD/%s/%s/latest/livecd-%s.out" % (
145- live_builder(config, arch), config.series, livefs_id, cpuarch)
146- with closing(urlopen(log_url, timeout=30)) as f:
147- body = f.read()
148+ if lp_build.build_log_url is None:
149+ raise URLError(
150+ "Failed build %s has no build_log_url" % lp_build.web_link)
151+ with closing(urlopen(lp_build.build_log_url, timeout=30)) as comp:
152+ with closing(io.BytesIO(comp.read())) as comp_bytes:
153+ with closing(GzipFile(fileobj=comp_bytes)) as f:
154+ body = f.read()
155 except URLError:
156 body = b""
157 subject = "LiveFS %s%s/%s/%s failed to build on %s" % (
158@@ -323,10 +228,7 @@ def live_lp_info(config, arch):
159
160
161 def get_lp_livefs(config, arch):
162- try:
163- lp_info = live_lp_info(config, arch)
164- except UnknownLaunchpadLiveFS:
165- return None, None
166+ lp_info = live_lp_info(config, arch)
167 if len(lp_info) > 2:
168 instance, owner, name = lp_info
169 else:
170@@ -346,7 +248,6 @@ def get_lp_livefs(config, arch):
171
172
173 def run_live_builds(config):
174- builds = {}
175 lp_builds = []
176 for arch in config.arches:
177 if arch == "amd64+mac":
178@@ -355,47 +256,38 @@ def run_live_builds(config):
179 full_name = live_build_full_name(config, arch)
180 timestamp = time.strftime("%F %T")
181 lp, lp_livefs = get_lp_livefs(config, arch)
182- if lp_livefs is None:
183- machine = live_builder(config, arch)
184- else:
185- machine = "Launchpad"
186- logger.info(
187- "%s on %s starting at %s" % (full_name, machine, timestamp))
188+ logger.info("%s on Launchpad starting at %s" % (full_name, timestamp))
189 tracker_set_rebuild_status(config, [0, 1], 2, arch)
190- if lp_livefs is not None:
191- lp_build = None
192- if config["CDIMAGE_REUSE_BUILD"]:
193- cpuarch, subarch = split_arch(config, arch)
194- for build in lp_livefs.builds:
195- try:
196- metadata_subarch = build.metadata_override.get(
197- "subarch", "")
198- except AttributeError:
199- metadata_subarch = ""
200- if (build.distro_arch_series.architecture_tag == cpuarch
201- and metadata_subarch == subarch
202- and build.buildstate == "Successfully built"):
203- logger.info("reusing build %s", build)
204- lp_build = build
205- break
206- else:
207- raise Exception("no build found to reuse for %s" % (arch,))
208- if lp_build is None:
209- lp_kwargs = live_build_lp_kwargs(config, lp, lp_livefs, arch)
210- lp_build = lp_livefs.requestBuild(**lp_kwargs)
211- logger.info("%s: %s" % (full_name, lp_build.web_link))
212- lp_builds.append((lp_build, arch, full_name, machine, None))
213- else:
214- proc = subprocess.Popen(live_build_command(config, arch))
215- builds[proc.pid] = (proc, arch, full_name, machine)
216+ lp_build = None
217+ if config["CDIMAGE_REUSE_BUILD"]:
218+ cpuarch, subarch = split_arch(config, arch)
219+ for build in lp_livefs.builds:
220+ try:
221+ metadata_subarch = build.metadata_override.get(
222+ "subarch", "")
223+ except AttributeError:
224+ metadata_subarch = ""
225+ if (build.distro_arch_series.architecture_tag == cpuarch
226+ and metadata_subarch == subarch
227+ and build.buildstate == "Successfully built"):
228+ logger.info("reusing build %s", build)
229+ lp_build = build
230+ break
231+ else:
232+ raise Exception("no build found to reuse for %s" % (arch,))
233+ if lp_build is None:
234+ lp_kwargs = live_build_lp_kwargs(config, lp, lp_livefs, arch)
235+ lp_build = lp_livefs.requestBuild(**lp_kwargs)
236+ print(lp_build)
237+ logger.info("%s: %s" % (full_name, lp_build.web_link))
238+ lp_builds.append((lp_build, arch, full_name, None))
239
240 successful = set()
241
242- def live_build_finished(arch, full_name, machine, status, text_status,
243- lp_build=None):
244+ def live_build_finished(arch, full_name, status, text_status, lp_build):
245 timestamp = time.strftime("%F %T")
246- logger.info("%s on %s finished at %s (%s)" % (
247- full_name, machine, timestamp, text_status))
248+ logger.info("%s on Launchpad finished at %s (%s)" % (
249+ full_name, timestamp, text_status))
250 if status == 0:
251 tracker_set_rebuild_status(config, [0, 1, 2], 3, arch)
252 successful.add(arch)
253@@ -405,28 +297,20 @@ def run_live_builds(config):
254 tracker_set_rebuild_status(config, [0, 1, 2], 5, arch)
255 live_build_notify_failure(config, arch, lp_build=lp_build)
256
257- while builds or lp_builds:
258- # Check for non-Launchpad build results.
259- for pid, (proc, arch, full_name, machine) in list(builds.items()):
260- status = proc.poll()
261- if status is not None:
262- del builds[pid]
263- live_build_finished(
264- arch, full_name, machine, status,
265- "success" if status == 0 else "failed")
266-
267+ while lp_builds:
268 # Check for Launchpad build results.
269 pending_lp_builds = []
270 for lp_item in lp_builds:
271- lp_build, arch, full_name, machine, log_timeout = lp_item
272+ lp_build, arch, full_name, log_timeout = lp_item
273 lp_build.lp_refresh()
274- if lp_build.buildstate in (
275+ bs = lp_build.buildstate
276+ if bs in (
277 "Needs building", "Currently building",
278 "Gathering build output", "Uploading build"):
279 pending_lp_builds.append(lp_item)
280 elif lp_build.buildstate == "Successfully built":
281 live_build_finished(
282- arch, full_name, machine, 0, lp_build.buildstate,
283+ arch, full_name, 0, lp_build.buildstate,
284 lp_build=lp_build)
285 elif (lp_build.build_log_url is None and
286 (log_timeout is None or time.time() < log_timeout)):
287@@ -436,17 +320,15 @@ def run_live_builds(config):
288 if log_timeout is None:
289 log_timeout = time.time() + 300
290 pending_lp_builds.append(
291- (lp_build, arch, full_name, machine, log_timeout))
292+ (lp_build, arch, full_name, log_timeout))
293 else:
294 live_build_finished(
295- arch, full_name, machine, 1, lp_build.buildstate,
296+ arch, full_name, 1, lp_build.buildstate,
297 lp_build=lp_build)
298 lp_builds = pending_lp_builds
299
300 if lp_builds:
301- # Wait a while before polling Launchpad again. If a
302- # non-Launchpad build completes in the meantime, it will
303- # interrupt this sleep with SIGCHLD.
304+ # Wait a while before polling Launchpad again.
305 time.sleep(15)
306
307 if not successful:
308@@ -454,29 +336,6 @@ def run_live_builds(config):
309 return successful
310
311
312-def livecd_base(config, arch):
313- if config["LIVECD_BASE"]:
314- return config["LIVECD_BASE"]
315-
316- cpuarch, subarch = split_arch(config, arch)
317- series = config["DIST"]
318-
319- if config["LIVECD"]:
320- root = config["LIVECD"]
321- else:
322- root = "http://%s/~buildd/LiveCD" % live_builder(config, arch)
323-
324- liveproject = live_project(config, arch)
325- if config["SUBPROJECT"]:
326- liveproject += "-%s" % config["SUBPROJECT"]
327- if subarch:
328- liveproject += "-%s" % subarch
329- if config["UBUNTU_DEFAULTS_LOCALE"]:
330- liveproject += "-%s" % config["UBUNTU_DEFAULTS_LOCALE"]
331-
332- return "%s/%s/%s/current" % (root, series, liveproject)
333-
334-
335 def flavours(config, arch):
336 cpuarch, subarch = split_arch(config, arch)
337 project = config.project
338@@ -552,31 +411,18 @@ def live_item_paths(config, arch, item):
339
340 lp, lp_livefs = get_lp_livefs(config, arch)
341 uris = []
342- root = ""
343- if lp_livefs is not None:
344- lp_kwargs = live_build_lp_kwargs(config, lp, lp_livefs, arch)
345- lp_build = lp_livefs.getLatestBuild(
346- lp_kwargs["distro_arch_series"],
347- unique_key=lp_kwargs.get("unique_key"))
348- uris = list(lp_build.getFileUrls())
349- else:
350- root = livecd_base(config, arch)
351- try:
352- uris = [os.path.join(root, u) for u in os.listdir(root)]
353- except OSError:
354- # fallback to exact given uri (for http://) in url_for as we can't
355- # list content.
356- pass
357+ lp_kwargs = live_build_lp_kwargs(config, lp, lp_livefs, arch)
358+ lp_build = lp_livefs.getLatestBuild(
359+ lp_kwargs["distro_arch_series"],
360+ unique_key=lp_kwargs.get("unique_key"))
361+ uris = list(lp_build.getFileUrls())
362
363 def urls_for(base, item):
364- if uris:
365- for uri in uris:
366- filename = unquote(os.path.basename(uri))
367- if (filename.startswith(base + '.') and
368- filename.endswith('.' + item)):
369- yield uri
370- else:
371- yield os.path.join(root, base + '.' + item)
372+ for uri in uris:
373+ filename = unquote(os.path.basename(uri))
374+ if (filename.startswith(base + '.') and
375+ filename.endswith('.' + item)):
376+ yield uri
377
378 if item in (
379 "cloop", "squashfs", "manifest", "manifest-desktop", "manifest-remove",
380@@ -775,7 +621,6 @@ def write_autorun(config, arch, name, label):
381
382 def download_live_filesystems(config):
383 project = config.project
384- series = config["DIST"]
385
386 output_dir = live_output_directory(config)
387 osextras.mkemptydir(output_dir)
388@@ -849,27 +694,6 @@ def download_live_filesystems(config):
389 config.subproject == "wubi"):
390 continue
391
392- if (project not in ("livecd-base", "ubuntu-base", "ubuntu-core",
393- "ubuntu-core-desktop", "ubuntu-appliance") and
394- (project != "ubuntukylin" or series <= "trusty")):
395- if series <= "trusty":
396- # TODO: We still have to do something about not
397- # including Wubi on the DVDs.
398- download_live_items(config, arch, "wubi")
399- wubi_path = os.path.join(output_dir, "%s.wubi.exe" % arch)
400- if os.path.exists(wubi_path):
401- # Nicely format the distribution name.
402- def upper_first(m):
403- text = m.group(0)
404- return text[0].upper() + text[1:]
405-
406- autorun_project = re.sub(
407- r"(\b[a-z])", upper_first,
408- project.replace("-", " "))
409- write_autorun(
410- config, arch, "wubi.exe",
411- "Install %s" % autorun_project)
412-
413 if (project in ("ubuntu-core", "ubuntu-core-desktop",
414 "ubuntu-appliance") and
415 config["CDIMAGE_LIVE"]):
416@@ -880,31 +704,6 @@ def download_live_filesystems(config):
417 if not got_image:
418 raise NoFilesystemImages("No filesystem images found.")
419
420- if config.project == "ubuntu-touch":
421- for arch in config.arches:
422- for abootimg in (
423- "boot-%s+%s.img" % (target.ubuntu_arch, target.subarch)
424- for target in Touch.list_targets_by_ubuntu_arch(arch)
425- ):
426- download_live_items(
427- config, arch, abootimg
428- )
429- for recoveryimg in (
430- "recovery-%s+%s.img" % (target.android_arch, target.subarch)
431- for target in Touch.list_targets_by_ubuntu_arch(arch)
432- ):
433- download_live_items(
434- config, arch, recoveryimg
435- )
436- for systemimg in (
437- "system-%s+%s.img" % (target.android_arch, target.subarch)
438- for target in Touch.list_targets_by_ubuntu_arch(arch)
439- ):
440- download_live_items(
441- config, arch, systemimg
442- )
443- download_live_items(config, arch, "custom.tar.gz")
444-
445 if config.project == "ubuntu-core":
446 for arch in config.arches:
447 download_live_items(config, arch, "device.tar.gz")
448diff --git a/lib/cdimage/tests/test_livefs.py b/lib/cdimage/tests/test_livefs.py
449index 6ef8055..a92bb66 100644
450--- a/lib/cdimage/tests/test_livefs.py
451+++ b/lib/cdimage/tests/test_livefs.py
452@@ -20,6 +20,7 @@
453 from __future__ import print_function
454
455 from collections import defaultdict
456+import gzip
457 from itertools import chain, repeat
458 import os
459 import subprocess
460@@ -40,19 +41,14 @@ from cdimage import osextras
461 from cdimage.config import Config, all_series
462 from cdimage.launchpad import get_launchpad, launchpad_available
463 from cdimage.livefs import (
464- LiveBuildsFailed,
465 download_live_filesystems,
466 download_live_items,
467 flavours,
468- live_build_command,
469 live_build_full_name,
470 live_build_notify_failure,
471- live_build_options,
472- live_builder,
473 live_item_paths,
474 live_output_directory,
475 live_project,
476- livecd_base,
477 run_live_builds,
478 split_arch,
479 write_autorun,
480@@ -125,7 +121,6 @@ class MockLiveFSBuild(mock.MagicMock):
481 class MockLiveFS(mock.MagicMock):
482 def requestBuild(self, distro_arch_series=None, **kwargs):
483 build = MockLiveFSBuild(distro_arch_series=distro_arch_series)
484- build.buildstate = "Needs building"
485 return build
486
487
488@@ -233,199 +228,6 @@ def make_livefs_production_config(config):
489 """), file=f)
490
491
492-class TestLiveBuilder(TestCase):
493- def setUp(self):
494- super(TestLiveBuilder, self).setUp()
495- self.config = Config(read=False)
496- self.config.root = self.use_temp_dir()
497- make_livefs_production_config(self.config)
498-
499- def assertBuilderEqual(self, expected, arch, series, project=None):
500- self.config["DIST"] = series
501- if project is not None:
502- self.config["PROJECT"] = project
503- self.assertEqual(expected, live_builder(self.config, arch))
504-
505- def test_amd64(self):
506- for series in all_series:
507- self.assertBuilderEqual("kapok.buildd", "amd64", series)
508-
509- def test_armel(self):
510- for series in all_series:
511- self.assertBuilderEqual("celbalrai.buildd", "armel", series)
512-
513- def test_arm64(self):
514- for series in all_series:
515- self.assertBuilderEqual("magic.buildd", "arm64", series)
516-
517- def test_armhf(self):
518- for series in all_series:
519- self.assertBuilderEqual(
520- "kishi00.buildd", "armhf+mx5", series, project="ubuntu")
521- self.assertBuilderEqual(
522- "kishi00.buildd", "armhf+omap", series, project="ubuntu")
523- self.assertBuilderEqual(
524- "kishi00.buildd", "armhf+omap4", series, project="ubuntu")
525- self.assertBuilderEqual(
526- "kishi00.buildd", "armhf+omap", series,
527- project="ubuntu-server")
528- self.assertBuilderEqual(
529- "celbalrai.buildd", "armhf+omap4", series,
530- project="ubuntu-server")
531- self.assertBuilderEqual("celbalrai.buildd", "armhf+ac100", series)
532- self.assertBuilderEqual("celbalrai.buildd", "armhf+nexus7", series)
533- self.assertBuilderEqual(
534- "kishi00.buildd", "armhf+somethingelse", series)
535-
536- def test_hppa(self):
537- for series in all_series:
538- self.assertBuilderEqual("castilla.buildd", "hppa", series)
539-
540- def test_i386(self):
541- for series in all_series:
542- self.assertBuilderEqual("cardamom.buildd", "i386", series)
543-
544- def test_ia64(self):
545- for series in all_series:
546- self.assertBuilderEqual("weddell.buildd", "ia64", series)
547-
548- def test_powerpc(self):
549- for series in all_series:
550- self.assertBuilderEqual("royal.buildd", "powerpc", series)
551-
552- def test_ppc64el(self):
553- for series in all_series:
554- self.assertBuilderEqual("fisher01.buildd", "ppc64el", series)
555-
556- def test_sparc(self):
557- for series in all_series:
558- self.assertBuilderEqual("vivies.buildd", "sparc", series)
559-
560-
561-class TestLiveBuildOptions(TestCase):
562- def setUp(self):
563- super(TestLiveBuildOptions, self).setUp()
564- self.config = Config(read=False)
565-
566- def test_armel_preinstalled(self):
567- self.config["IMAGE_TYPE"] = "daily-preinstalled"
568- for subarch, fstype in (
569- ("mx5", "ext4"),
570- ("omap", "ext4"),
571- ("omap4", "ext4"),
572- ("ac100", "plain"),
573- ("nexus7", "plain"),
574- ):
575- self.assertEqual(
576- ["-f", fstype],
577- live_build_options(self.config, "armel+%s" % subarch))
578- self.assertEqual([], live_build_options(self.config, "armel+other"))
579-
580- def test_armhf_preinstalled(self):
581- self.config["IMAGE_TYPE"] = "daily-preinstalled"
582- for subarch, fstype in (
583- ("mx5", "ext4"),
584- ("omap", "ext4"),
585- ("omap4", "ext4"),
586- ("ac100", "plain"),
587- ("nexus7", "plain"),
588- ):
589- self.assertEqual(
590- ["-f", fstype],
591- live_build_options(self.config, "armhf+%s" % subarch))
592- self.assertEqual([], live_build_options(self.config, "armhf+other"))
593-
594- def test_ubuntu_core(self):
595- self.config["PROJECT"] = "ubuntu-core"
596- self.assertEqual(
597- ["-f", "plain"], live_build_options(self.config, "i386"))
598-
599- def test_ubuntu_base(self):
600- self.config["PROJECT"] = "ubuntu-base"
601- self.assertEqual(
602- ["-f", "plain"], live_build_options(self.config, "i386"))
603-
604- def test_ubuntu_touch(self):
605- self.config["PROJECT"] = "ubuntu-touch"
606- self.assertEqual(
607- ["-f", "plain"], live_build_options(self.config, "armhf"))
608-
609- def test_wubi(self):
610- self.config["SUBPROJECT"] = "wubi"
611- for series, fstype in (
612- ("trusty", "ext3"), # ext4
613- ):
614- self.config["DIST"] = series
615- self.assertEqual(
616- ["-f", fstype], live_build_options(self.config, "i386"))
617-
618-
619-class TestLiveBuildCommand(TestCase):
620- def setUp(self):
621- super(TestLiveBuildCommand, self).setUp()
622- self.config = Config(read=False)
623- self.config.root = self.use_temp_dir()
624- make_livefs_production_config(self.config)
625- self.base_expected = [
626- "ssh", "-n", "-o", "StrictHostKeyChecking=no",
627- "-o", "BatchMode=yes",
628- ]
629-
630- def contains_subsequence(self, haystack, needle):
631- # This is inefficient, but it doesn't matter much here.
632- for i in range(len(haystack) - len(needle) + 1):
633- if haystack[i:i + len(needle)] == needle:
634- return True
635- return False
636-
637- def assertCommandContains(self, subsequence, arch):
638- observed = live_build_command(self.config, arch)
639- if not self.contains_subsequence(observed, subsequence):
640- self.fail("%s does not contain %s" % (observed, subsequence))
641-
642- def test_basic(self):
643- self.config["PROJECT"] = "ubuntu"
644- self.config["DIST"] = "trusty"
645- expected = self.base_expected + [
646- "buildd@cardamom.buildd", "/home/buildd/bin/BuildLiveCD",
647- "-l", "-A", "i386", "-d", "trusty", "ubuntu",
648- ]
649- self.assertEqual(expected, live_build_command(self.config, "i386"))
650-
651- def test_ubuntu_defaults_locale(self):
652- self.config["UBUNTU_DEFAULTS_LOCALE"] = "zh_CN"
653- self.assertCommandContains(["-u", "zh_CN"], "i386")
654-
655- def test_pre_live_build(self):
656- self.config["DIST"] = "trusty"
657- self.assertIn("-l", live_build_command(self.config, "i386"))
658-
659- @mock.patch(
660- "cdimage.livefs.live_build_options", return_value=["-f", "plain"])
661- def test_uses_live_build_options(self, *args):
662- self.assertCommandContains(["-f", "plain"], "i386")
663-
664- def test_subarch(self):
665- self.assertCommandContains(["-s", "omap4"], "armhf+omap4")
666-
667- def test_proposed(self):
668- self.config["PROPOSED"] = "1"
669- self.assertIn("-p", live_build_command(self.config, "i386"))
670-
671- def test_series(self):
672- self.config["DIST"] = "trusty"
673- self.assertCommandContains(["-d", "trusty"], "i386")
674-
675- def test_subproject(self):
676- self.config["SUBPROJECT"] = "wubi"
677- self.assertCommandContains(["-r", "wubi"], "i386")
678-
679- def test_project(self):
680- self.config["PROJECT"] = "kubuntu"
681- self.assertEqual(
682- "kubuntu", live_build_command(self.config, "i386")[-1])
683-
684-
685 def mock_strftime(secs):
686 original_strftime = time.strftime
687 gmtime = time.gmtime(secs)
688@@ -472,12 +274,12 @@ class TestRunLiveBuilds(TestCase):
689 @mock.patch("cdimage.livefs.get_notify_addresses")
690 def test_live_build_notify_failure_debug(self, mock_notify_addresses):
691 self.config["DEBUG"] = "1"
692- live_build_notify_failure(self.config, None)
693+ live_build_notify_failure(self.config, None, MockLiveFSBuild())
694 self.assertEqual(0, mock_notify_addresses.call_count)
695
696 @mock.patch("cdimage.livefs.send_mail")
697 def test_live_build_notify_failure_no_recipients(self, mock_send_mail):
698- live_build_notify_failure(self.config, None)
699+ live_build_notify_failure(self.config, None, MockLiveFSBuild())
700 self.assertEqual(0, mock_send_mail.call_count)
701
702 @mock.patch("time.strftime", return_value="20130315")
703@@ -491,7 +293,7 @@ class TestRunLiveBuilds(TestCase):
704 path = os.path.join(self.temp_dir, "production", "notify-addresses")
705 with mkfile(path) as notify_addresses:
706 print("ALL\tfoo@example.org", file=notify_addresses)
707- live_build_notify_failure(self.config, "i386")
708+ live_build_notify_failure(self.config, "i386", MockLiveFSBuild())
709 mock_send_mail.assert_called_once_with(
710 "LiveFS ubuntu/trusty/i386 failed to build on 20130315",
711 "buildlive", ["foo@example.org"], b"")
712@@ -505,178 +307,18 @@ class TestRunLiveBuilds(TestCase):
713 path = os.path.join(self.temp_dir, "production", "notify-addresses")
714 with mkfile(path) as notify_addresses:
715 print("ALL\tfoo@example.org", file=notify_addresses)
716- mock_urlopen_obj = mock_urlopen(b"Log data\n")
717+ mock_urlopen_obj = mock_urlopen(gzip.compress(b"Log data\n"))
718+ mock_build = MockLiveFSBuild()
719+ mock_build.build_log_url = 'http://log-location'
720 with mock.patch("cdimage.livefs.urlopen", mock_urlopen_obj):
721- live_build_notify_failure(self.config, "armhf+omap4")
722+ live_build_notify_failure(self.config, "armhf+omap4", mock_build)
723 mock_urlopen_obj.assert_called_once_with(
724- "http://kishi00.buildd/~buildd/LiveCD/trusty/kubuntu-omap4/latest/"
725- "livecd-armhf.out", timeout=30)
726+ mock_build.build_log_url, timeout=30)
727 mock_send_mail.assert_called_once_with(
728 "LiveFS kubuntu-omap4/trusty/armhf+omap4 failed to build on "
729 "20130315",
730 "buildlive", ["foo@example.org"], b"Log data\n")
731
732- @mock_strftime(1363355331)
733- @mock.patch("cdimage.livefs.live_build_command", return_value=["false"])
734- @mock.patch("cdimage.livefs.tracker_set_rebuild_status")
735- @mock.patch("cdimage.livefs.send_mail")
736- def test_run_live_builds_notifies_on_failure(self, mock_send_mail,
737- mock_tracker, *args):
738- self.config["PROJECT"] = "ubuntu"
739- self.config["DIST"] = "trusty"
740- self.config["IMAGE_TYPE"] = "daily"
741- self.config["ARCHES"] = "amd64 i386"
742- path = os.path.join(self.temp_dir, "production", "notify-addresses")
743- with mkfile(path) as notify_addresses:
744- print("ALL\tfoo@example.org", file=notify_addresses)
745- self.capture_logging()
746- with mock.patch("cdimage.livefs.urlopen", mock_urlopen(b"Log data\n")):
747- self.assertRaisesRegex(
748- LiveBuildsFailed, "No live filesystem builds succeeded.",
749- run_live_builds, self.config)
750- self.assertCountEqual([
751- "ubuntu-amd64 on kapok.buildd starting at 2013-03-15 13:48:51",
752- "ubuntu-i386 on cardamom.buildd starting at 2013-03-15 13:48:51",
753- "ubuntu-amd64 on kapok.buildd finished at 2013-03-15 13:48:51 "
754- "(failed)",
755- "ubuntu-i386 on cardamom.buildd finished at 2013-03-15 13:48:51 "
756- "(failed)",
757- ], self.captured_log_messages())
758- mock_send_mail.assert_has_calls([
759- mock.call(
760- "LiveFS ubuntu/trusty/amd64 failed to build on 20130315",
761- "buildlive", ["foo@example.org"], b"Log data\n"),
762- mock.call(
763- "LiveFS ubuntu/trusty/i386 failed to build on 20130315",
764- "buildlive", ["foo@example.org"], b"Log data\n"),
765- ], any_order=True)
766- mock_tracker.assert_has_calls([
767- mock.call(self.config, [0, 1], 2, "amd64"),
768- mock.call(self.config, [0, 1], 2, "i386"),
769- mock.call(self.config, [0, 1, 2], 5, "amd64"),
770- mock.call(self.config, [0, 1, 2], 5, "i386")
771- ])
772-
773- @mock_strftime(1363355331)
774- @mock.patch("cdimage.livefs.tracker_set_rebuild_status")
775- @mock_Popen(["true"])
776- @mock.patch("cdimage.livefs.live_build_notify_failure")
777- def test_run_live_builds(self, mock_live_build_notify_failure, mock_popen,
778- mock_tracker_set_rebuild_status, *args):
779- self.config["PROJECT"] = "ubuntu"
780- self.config["DIST"] = "trusty"
781- self.config["IMAGE_TYPE"] = "daily"
782- self.config["ARCHES"] = "amd64 i386"
783- self.capture_logging()
784- self.assertCountEqual(["amd64", "i386"], run_live_builds(self.config))
785- self.assertCountEqual([
786- "ubuntu-amd64 on kapok.buildd starting at 2013-03-15 13:48:51",
787- "ubuntu-i386 on cardamom.buildd starting at 2013-03-15 13:48:51",
788- "ubuntu-amd64 on kapok.buildd finished at 2013-03-15 13:48:51 "
789- "(success)",
790- "ubuntu-i386 on cardamom.buildd finished at 2013-03-15 13:48:51 "
791- "(success)",
792- ], self.captured_log_messages())
793- self.assertEqual(4, mock_tracker_set_rebuild_status.call_count)
794- mock_tracker_set_rebuild_status.assert_has_calls([
795- mock.call(self.config, [0, 1], 2, "amd64"),
796- mock.call(self.config, [0, 1], 2, "i386"),
797- mock.call(self.config, [0, 1, 2], 3, "amd64"),
798- mock.call(self.config, [0, 1, 2], 3, "i386"),
799- ])
800- expected_command_base = [
801- "ssh", "-n", "-o", "StrictHostKeyChecking=no",
802- "-o", "BatchMode=yes",
803- ]
804- mock_popen.assert_has_calls([
805- mock.call(
806- expected_command_base + [
807- "buildd@kapok.buildd", "/home/buildd/bin/BuildLiveCD",
808- "-l", "-A", "amd64", "-d", "trusty", "ubuntu",
809- ]),
810- mock.call(
811- expected_command_base + [
812- "buildd@cardamom.buildd", "/home/buildd/bin/BuildLiveCD",
813- "-l", "-A", "i386", "-d", "trusty", "ubuntu",
814- ])
815- ])
816- self.assertEqual(0, mock_live_build_notify_failure.call_count)
817-
818- @mock.patch("cdimage.livefs.tracker_set_rebuild_status")
819- @mock_Popen(["true"])
820- @mock.patch("cdimage.livefs.live_build_notify_failure")
821- def test_run_live_builds_skips_amd64_mac(self,
822- mock_live_build_notify_failure,
823- mock_popen, *args):
824- self.config["PROJECT"] = "ubuntu"
825- self.config["DIST"] = "trusty"
826- self.config["IMAGE_TYPE"] = "daily"
827- self.config["ARCHES"] = "amd64 amd64+mac"
828- self.capture_logging()
829- self.assertCountEqual(
830- ["amd64", "amd64+mac"], run_live_builds(self.config))
831- expected_command = [
832- "ssh", "-n", "-o", "StrictHostKeyChecking=no",
833- "-o", "BatchMode=yes",
834- "buildd@kapok.buildd", "/home/buildd/bin/BuildLiveCD",
835- "-l", "-A", "amd64", "-d", "trusty", "ubuntu",
836- ]
837- mock_popen.assert_called_once_with(expected_command)
838- self.assertEqual(0, mock_live_build_notify_failure.call_count)
839-
840- @mock_strftime(1363355331)
841- @mock.patch("cdimage.livefs.urlopen", mock_urlopen(b"Log data\n"))
842- @mock.patch("cdimage.livefs.tracker_set_rebuild_status")
843- @mock.patch("cdimage.livefs.send_mail")
844- def test_run_live_builds_partial_success(self, mock_send_mail, *args):
845- self.config["PROJECT"] = "ubuntu"
846- self.config["DIST"] = "trusty"
847- self.config["IMAGE_TYPE"] = "daily"
848- self.config["ARCHES"] = "amd64 i386"
849- path = os.path.join(self.temp_dir, "production", "notify-addresses")
850- with mkfile(path) as notify_addresses:
851- print("ALL\tfoo@example.org", file=notify_addresses)
852- self.capture_logging()
853- original_Popen = subprocess.Popen
854- with mock.patch("subprocess.Popen") as mock_popen:
855- def Popen_side_effect(command, *args, **kwargs):
856- if "amd64" in command:
857- return original_Popen(["true"])
858- else:
859- return original_Popen(["false"])
860-
861- mock_popen.side_effect = Popen_side_effect
862- self.assertCountEqual(["amd64"], run_live_builds(self.config))
863- self.assertCountEqual([
864- "ubuntu-amd64 on kapok.buildd starting at 2013-03-15 13:48:51",
865- "ubuntu-i386 on cardamom.buildd starting at "
866- "2013-03-15 13:48:51",
867- "ubuntu-amd64 on kapok.buildd finished at "
868- "2013-03-15 13:48:51 (success)",
869- "ubuntu-i386 on cardamom.buildd finished at "
870- "2013-03-15 13:48:51 (failed)",
871- ], self.captured_log_messages())
872- expected_command_base = [
873- "ssh", "-n", "-o", "StrictHostKeyChecking=no",
874- "-o", "BatchMode=yes",
875- ]
876- mock_popen.assert_has_calls([
877- mock.call(
878- expected_command_base + [
879- "buildd@kapok.buildd", "/home/buildd/bin/BuildLiveCD",
880- "-l", "-A", "amd64", "-d", "trusty", "ubuntu",
881- ]),
882- mock.call(
883- expected_command_base + [
884- "buildd@cardamom.buildd",
885- "/home/buildd/bin/BuildLiveCD",
886- "-l", "-A", "i386", "-d", "trusty", "ubuntu",
887- ]),
888- ])
889- mock_send_mail.assert_called_once_with(
890- "LiveFS ubuntu/trusty/i386 failed to build on 20130315",
891- "buildlive", ["foo@example.org"], b"Log data\n")
892-
893 @skipUnless(launchpad_available, "launchpadlib not available")
894 @mock_strftime(1363355331)
895 @mock.patch("time.sleep")
896@@ -738,128 +380,6 @@ class TestRunLiveBuilds(TestCase):
897 self.assertEqual("Successfully built", builds[1].buildstate)
898 self.assertEqual(0, mock_live_build_notify_failure.call_count)
899
900- @skipUnless(launchpad_available, "launchpadlib not available")
901- @mock_strftime(1363355331)
902- @mock.patch("time.sleep")
903- @mock.patch("cdimage.livefs.tracker_set_rebuild_status")
904- @mock.patch("cdimage.livefs.live_build_notify_failure")
905- @mock.patch("cdimage.tests.test_livefs.MockLiveFSBuild._iter_buildstate")
906- @mock.patch("cdimage.launchpad.login")
907- def test_run_live_builds_lp_ubuntu_rtm(self, mock_login,
908- mock_iter_buildstate,
909- mock_live_build_notify_failure,
910- mock_tracker_set_rebuild_status,
911- mock_sleep, *args):
912- self.config["PROJECT"] = "ubuntu-touch"
913- self.config["DIST"] = "ubuntu-rtm/14.09"
914- self.config["IMAGE_TYPE"] = "daily-preinstalled"
915- self.config["ARCHES"] = "armhf i386"
916- osextras.unlink_force(os.path.join(
917- self.config.root, "production", "livefs-builders"))
918- with mkfile(os.path.join(
919- self.config.root, "production", "livefs-launchpad")) as f:
920- print(
921- "ubuntu-touch\tdaily-preinstalled\tubuntu-rtm/*\t*\t"
922- "dogfood/ubuntu-cdimage/ubuntu-touch", file=f)
923- print(
924- "ubuntu-touch\tdaily-preinstalled\t*\t*\t"
925- "ubuntu-cdimage/ubuntu-touch", file=f)
926- self.capture_logging()
927- mock_login.return_value = MockLaunchpad()
928- mock_iter_buildstate.side_effect = lambda: (
929- chain(["Needs building"] * 3, repeat("Successfully built")))
930- self.assertCountEqual(["armhf", "i386"], run_live_builds(self.config))
931- self.assertCountEqual([
932- "ubuntu-touch-armhf on Launchpad starting at 2013-03-15 13:48:51",
933- "ubuntu-touch-armhf: https://launchpad.example/armhf-build",
934- "ubuntu-touch-i386 on Launchpad starting at 2013-03-15 13:48:51",
935- "ubuntu-touch-i386: https://launchpad.example/i386-build",
936- "ubuntu-touch-armhf on Launchpad finished at 2013-03-15 13:48:51 "
937- "(Successfully built)",
938- "ubuntu-touch-i386 on Launchpad finished at 2013-03-15 13:48:51 "
939- "(Successfully built)",
940- ], self.captured_log_messages())
941- self.assertEqual(4, mock_tracker_set_rebuild_status.call_count)
942- mock_tracker_set_rebuild_status.assert_has_calls([
943- mock.call(self.config, [0, 1], 2, "armhf"),
944- mock.call(self.config, [0, 1], 2, "i386"),
945- mock.call(self.config, [0, 1, 2], 3, "armhf"),
946- mock.call(self.config, [0, 1, 2], 3, "i386"),
947- ])
948- self.assertEqual(3, mock_sleep.call_count)
949- mock_sleep.assert_has_calls([mock.call(15)] * 3)
950- lp = get_launchpad()
951- owner = lp.people["ubuntu-cdimage"]
952- ubuntu_rtm = lp.distributions["ubuntu-rtm"]
953- series = ubuntu_rtm.getSeries(name_or_version="14.09")
954- dases = [
955- series.getDistroArchSeries(archtag)
956- for archtag in ("armhf", "i386")]
957- self.assertEqual(2, len(dases))
958- livefs = lp.livefses.getByName(
959- owner=owner, distro_series=series, name="ubuntu-touch")
960- builds = [
961- livefs.getLatestBuild(distro_arch_series=das) for das in dases]
962- self.assertEqual(2, len(builds))
963- self.assertEqual("Successfully built", builds[0].buildstate)
964- self.assertEqual("Successfully built", builds[1].buildstate)
965- self.assertEqual(0, mock_live_build_notify_failure.call_count)
966-
967-
968-class TestLiveCDBase(TestCase):
969- def setUp(self):
970- super(TestLiveCDBase, self).setUp()
971- self.config = Config(read=False)
972- self.config.root = self.use_temp_dir()
973- make_livefs_production_config(self.config)
974-
975- def assertBaseEqual(self, expected, arch, project, series, **kwargs):
976- self.config["PROJECT"] = project
977- self.config["DIST"] = series
978- for key, value in kwargs.items():
979- self.config[key.upper()] = value
980- self.assertEqual(expected, livecd_base(self.config, arch))
981-
982- def base(self, builder, project, series):
983- return "http://%s/~buildd/LiveCD/%s/%s/current" % (
984- builder, series, project)
985-
986- def test_livecd_base_override(self):
987- self.assertBaseEqual(
988- "ftp://blah", "amd64", "ubuntu", "dapper",
989- livecd_base="ftp://blah")
990-
991- def test_livecd_override(self):
992- self.assertBaseEqual(
993- "ftp://blah/trusty/ubuntu/current", "i386", "ubuntu", "trusty",
994- livecd="ftp://blah")
995-
996- def test_subproject(self):
997- for series in all_series:
998- self.assertBaseEqual(
999- self.base("cardamom.buildd", "ubuntu-wubi", series),
1000- "i386", "ubuntu", series, subproject="wubi")
1001-
1002- def test_no_subarch(self):
1003- for series in all_series:
1004- self.assertBaseEqual(
1005- self.base("cardamom.buildd", "ubuntu", series),
1006- "i386", "ubuntu", series)
1007-
1008- def test_subarch(self):
1009- self.assertBaseEqual(
1010- self.base("royal.buildd", "ubuntu-ps3", "trusty"),
1011- "powerpc+ps3", "ubuntu", "trusty")
1012- self.assertBaseEqual(
1013- self.base("celbalrai.buildd", "ubuntu-server-omap", "trusty"),
1014- "armel+omap", "ubuntu-server", "trusty")
1015-
1016- def test_ubuntu_defaults_locale(self):
1017- for series in all_series:
1018- self.assertBaseEqual(
1019- self.base("cardamom.buildd", "ubuntu-zh_CN", series),
1020- "i386", "ubuntu", series, ubuntu_defaults_locale="zh_CN")
1021-
1022
1023 class TestFlavours(TestCase):
1024 def assertFlavoursEqual(self, expected, arch, project, series):
1025@@ -941,6 +461,10 @@ class TestLiveItemPaths(TestCase):
1026 super(TestLiveItemPaths, self).setUp()
1027 self.config = Config(read=False)
1028 self.config.root = self.use_temp_dir()
1029+ _patcher = mock.patch("cdimage.livefs.get_lp_livefs")
1030+ mock_lp_livefs = _patcher.start()
1031+ mock_lp_livefs.return_value = None, MockLiveFSBuild()
1032+ self.addCleanup(_patcher.stop)
1033 make_livefs_production_config(self.config)
1034
1035 def assertPathsEqual(self, expected, arch, item, project, series):

Subscribers

People subscribed via source and target branches