blob: 4a69f6f2f8deacc5ab911f7576dde6df37c3c88d [file] [log] [blame]
Evan Hernandezf388cbf2019-04-01 11:15:23 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Implements ArtifactService."""
7
8from __future__ import print_function
9
10import os
11
Alex Klein231d2da2019-07-22 16:44:45 -060012from chromite.api import controller
Alex Klein076841b2019-08-29 15:19:39 -060013from chromite.api import faux
Alex Klein2b236722019-06-19 15:44:26 -060014from chromite.api import validate
Alex Klein238d8862019-05-07 11:32:46 -060015from chromite.api.controller import controller_util
Tiancong Wang24a3df72019-08-20 15:48:51 -070016from chromite.api.gen.chromite.api import toolchain_pb2
Evan Hernandezf388cbf2019-04-01 11:15:23 -060017from chromite.cbuildbot import commands
Alex Klein2275d692019-04-23 16:04:12 -060018from chromite.lib import build_target_util
19from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060020from chromite.lib import constants
21from chromite.lib import cros_build_lib
Evan Hernandezde445982019-04-22 13:42:34 -060022from chromite.lib import cros_logging as logging
Alex Klein2275d692019-04-23 16:04:12 -060023from chromite.lib import sysroot_lib
24from chromite.service import artifacts
Evan Hernandezf388cbf2019-04-01 11:15:23 -060025
26
Evan Hernandez9f125ac2019-04-08 17:18:47 -060027def _GetImageDir(build_root, target):
28 """Return path containing images for the given build target.
29
Alex Kleine2612a02019-04-18 13:51:06 -060030 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
31
Evan Hernandez9f125ac2019-04-08 17:18:47 -060032 Args:
33 build_root (str): Path to checkout where build occurs.
34 target (str): Name of the build target.
35
36 Returns:
Alex Kleind2bf1462019-10-24 16:37:04 -060037 Path to the latest directory containing target images or None.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060038 """
39 image_dir = os.path.join(build_root, 'src/build/images', target, 'latest')
40 if not os.path.exists(image_dir):
Alex Kleind2bf1462019-10-24 16:37:04 -060041 logging.warning('Expected to find image output for target %s at %s, but '
42 'path does not exist', target, image_dir)
43 return None
44
Evan Hernandez9f125ac2019-04-08 17:18:47 -060045 return image_dir
46
47
Michael Mortensen2d6a2402019-11-26 13:40:40 -070048def _BundleImageArchivesResponse(input_proto, output_proto, _config):
49 """Add artifact paths to a successful response."""
50 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
51 'path0.tar.xz')
52 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
53 'path1.tar.xz')
54
55
56@faux.success(_BundleImageArchivesResponse)
57@faux.empty_error
Alex Kleind91e95a2019-09-17 10:39:02 -060058@validate.require('build_target.name')
59@validate.exists('output_dir')
60@validate.validation_complete
61def BundleImageArchives(input_proto, output_proto, _config):
62 """Create a .tar.xz archive for each image that has been created."""
63 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
64 output_dir = input_proto.output_dir
65 image_dir = _GetImageDir(constants.SOURCE_ROOT, build_target.name)
Alex Kleind2bf1462019-10-24 16:37:04 -060066 if image_dir is None:
67 return
Alex Kleind91e95a2019-09-17 10:39:02 -060068
69 archives = artifacts.ArchiveImages(image_dir, output_dir)
70
71 for archive in archives:
72 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
73
74
Michael Mortensen2d6a2402019-11-26 13:40:40 -070075def _BundleImageZipResponse(input_proto, output_proto, _config):
76 """Add artifact zip files to a successful response."""
77 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
78 'image.zip')
79
80
81@faux.success(_BundleImageZipResponse)
82@faux.empty_error
Michael Mortensen01910922019-07-24 14:48:10 -060083@validate.require('build_target.name', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -060084@validate.exists('output_dir')
85@validate.validation_complete
86def BundleImageZip(input_proto, output_proto, _config):
Evan Hernandez9f125ac2019-04-08 17:18:47 -060087 """Bundle image.zip.
88
89 Args:
90 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -060091 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -060092 _config (api_config.ApiConfig): The API call config.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060093 """
94 target = input_proto.build_target.name
95 output_dir = input_proto.output_dir
96 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
Alex Kleind2bf1462019-10-24 16:37:04 -060097 if image_dir is None:
98 return None
Alex Klein231d2da2019-07-22 16:44:45 -060099
Michael Mortensen01910922019-07-24 14:48:10 -0600100 archive = artifacts.BundleImageZip(output_dir, image_dir)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600101 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
102
103
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700104def _BundleTestUpdatePayloadsResponse(input_proto, output_proto, _config):
105 """Add test payload files to a successful response."""
106 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
107 'payload1.bin')
108
109
110@faux.success(_BundleTestUpdatePayloadsResponse)
111@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600112@validate.require('build_target.name', 'output_dir')
113@validate.exists('output_dir')
114@validate.validation_complete
115def BundleTestUpdatePayloads(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600116 """Generate minimal update payloads for the build target for testing.
117
118 Args:
119 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600120 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600121 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600122 """
123 target = input_proto.build_target.name
124 output_dir = input_proto.output_dir
125 build_root = constants.SOURCE_ROOT
126
127 # Use the first available image to create the update payload.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600128 img_dir = _GetImageDir(build_root, target)
Alex Kleind2bf1462019-10-24 16:37:04 -0600129 if img_dir is None:
130 return None
131
Alex Kleincb541e82019-06-26 15:06:11 -0600132 img_types = [constants.IMAGE_TYPE_TEST, constants.IMAGE_TYPE_DEV,
133 constants.IMAGE_TYPE_BASE]
134 img_names = [constants.IMAGE_TYPE_TO_NAME[t] for t in img_types]
Mike Frysinger66ce4132019-07-17 22:52:52 -0400135 img_paths = [os.path.join(img_dir, x) for x in img_names]
Mike Frysingera552be42018-08-17 14:39:32 -0400136 valid_images = [x for x in img_paths if os.path.exists(x)]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600137
Alex Kleincb541e82019-06-26 15:06:11 -0600138 if not valid_images:
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600139 cros_build_lib.Die(
140 'Expected to find an image of type among %r for target "%s" '
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600141 'at path %s.', img_types, target, img_dir)
Alex Kleincb541e82019-06-26 15:06:11 -0600142 image = valid_images[0]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600143
Alex Kleincb541e82019-06-26 15:06:11 -0600144 payloads = artifacts.BundleTestUpdatePayloads(image, output_dir)
145 for payload in payloads:
146 output_proto.artifacts.add().path = payload
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600147
148
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700149def _BundleAutotestFilesResponse(input_proto, output_proto, _config):
150 """Add test autotest files to a successful response."""
151 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
152 'autotest-a.tar.gz')
153
154
155@faux.success(_BundleAutotestFilesResponse)
156@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600157@validate.require('output_dir')
158@validate.exists('output_dir')
159def BundleAutotestFiles(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600160 """Tar the autotest files for a build target.
161
162 Args:
163 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600164 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600165 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600166 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600167 output_dir = input_proto.output_dir
Alex Klein238d8862019-05-07 11:32:46 -0600168 target = input_proto.build_target.name
Alex Kleine21a0952019-08-23 16:08:16 -0600169 chroot = controller_util.ParseChroot(input_proto.chroot)
170
Alex Klein238d8862019-05-07 11:32:46 -0600171 if target:
Alex Kleine21a0952019-08-23 16:08:16 -0600172 sysroot_path = os.path.join('/build', target)
Alex Klein238d8862019-05-07 11:32:46 -0600173 else:
174 # New style call, use chroot and sysroot.
Alex Klein238d8862019-05-07 11:32:46 -0600175 sysroot_path = input_proto.sysroot.path
176 if not sysroot_path:
177 cros_build_lib.Die('sysroot.path is required.')
178
Alex Kleine21a0952019-08-23 16:08:16 -0600179 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600180
Alex Klein231d2da2019-07-22 16:44:45 -0600181 # TODO(saklein): Switch to the validate_only decorator when legacy handling
182 # is removed.
183 if config.validate_only:
184 return controller.RETURN_CODE_VALID_INPUT
185
Alex Kleine21a0952019-08-23 16:08:16 -0600186 if not sysroot.Exists(chroot=chroot):
Alex Klein238d8862019-05-07 11:32:46 -0600187 cros_build_lib.Die('Sysroot path must exist: %s', sysroot.path)
188
189 try:
190 # Note that this returns the full path to *multiple* tarballs.
Alex Kleine21a0952019-08-23 16:08:16 -0600191 archives = artifacts.BundleAutotestFiles(chroot, sysroot, output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600192 except artifacts.Error as e:
Mike Frysinger6b5c3cd2019-08-27 16:51:00 -0400193 cros_build_lib.Die(e)
Alex Klein238d8862019-05-07 11:32:46 -0600194
195 for archive in archives.values():
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600196 output_proto.artifacts.add().path = archive
197
198
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700199def _BundleTastFilesResponse(input_proto, output_proto, _config):
200 """Add test tast files to a successful response."""
201 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
202 'tast_bundles.tar.gz')
203
204
205@faux.success(_BundleTastFilesResponse)
206@faux.empty_error
Alex Kleinb9d810b2019-07-01 12:38:02 -0600207@validate.require('output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600208@validate.exists('output_dir')
209def BundleTastFiles(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600210 """Tar the tast files for a build target.
211
212 Args:
213 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600214 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600215 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600216 """
217 target = input_proto.build_target.name
218 output_dir = input_proto.output_dir
219 build_root = constants.SOURCE_ROOT
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600220
Alex Kleinb9d810b2019-07-01 12:38:02 -0600221 chroot = controller_util.ParseChroot(input_proto.chroot)
222 sysroot_path = input_proto.sysroot.path
223
224 # TODO(saklein) Cleanup legacy handling after it has been switched over.
225 if target:
226 # Legacy handling.
Alex Klein171da612019-08-06 14:00:42 -0600227 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
Alex Kleinb9d810b2019-07-01 12:38:02 -0600228 sysroot_path = os.path.join('/build', target)
229
230 # New handling - chroot & sysroot based.
231 # TODO(saklein) Switch this to the require decorator when legacy is removed.
232 if not sysroot_path:
233 cros_build_lib.Die('sysroot.path is required.')
234
Alex Klein231d2da2019-07-22 16:44:45 -0600235 # TODO(saklein): Switch to the validation_complete decorator when legacy
236 # handling is removed.
237 if config.validate_only:
238 return controller.RETURN_CODE_VALID_INPUT
239
Alex Kleinb9d810b2019-07-01 12:38:02 -0600240 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -0600241 if not sysroot.Exists(chroot=chroot):
Alex Kleinb9d810b2019-07-01 12:38:02 -0600242 cros_build_lib.Die('Sysroot must exist.')
243
244 archive = artifacts.BundleTastFiles(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600245
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600246 if archive is None:
247 cros_build_lib.Die(
248 'Could not bundle Tast files. '
249 'No Tast directories found for %s.', target)
250
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600251 output_proto.artifacts.add().path = archive
252
253
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700254def _BundlePinnedGuestImagesResponse(input_proto, output_proto, _config):
255 """Add test pinned guest image files to a successful response."""
256 output_proto.artifacts.add().path = os.path.join(
257 input_proto.output_dir, 'pinned-guest-images.tar.gz')
258
259
260@faux.success(_BundlePinnedGuestImagesResponse)
261@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600262@validate.require('build_target.name', 'output_dir')
263@validate.exists('output_dir')
264@validate.validation_complete
265def BundlePinnedGuestImages(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600266 """Tar the pinned guest images for a build target.
267
268 Args:
269 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600270 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600271 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600272 """
273 target = input_proto.build_target.name
274 output_dir = input_proto.output_dir
275 build_root = constants.SOURCE_ROOT
276
Alex Kleine2612a02019-04-18 13:51:06 -0600277 # TODO(crbug.com/954299): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600278 archive = commands.BuildPinnedGuestImagesTarball(build_root, target,
279 output_dir)
280
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600281 if archive is None:
Evan Hernandezde445982019-04-22 13:42:34 -0600282 logging.warning('Found no pinned guest images for %s.', target)
283 return
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600284
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600285 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
286
287
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700288def _FetchPinnedGuestImagesResponse(_input_proto, output_proto, _config):
289 """Add test fetched pinned guest image files to a successful response."""
290 pinned_image = output_proto.pinned_images.add()
291 pinned_image.filename = 'pinned_file.tar.gz'
292 pinned_image.uri = 'https://testuri.com'
293
294
295@faux.success(_FetchPinnedGuestImagesResponse)
296@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600297@validate.require('sysroot.path')
298@validate.validation_complete
299def FetchPinnedGuestImages(input_proto, output_proto, _config):
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600300 """Get the pinned guest image information."""
301 sysroot_path = input_proto.sysroot.path
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600302
303 chroot = controller_util.ParseChroot(input_proto.chroot)
304 sysroot = sysroot_lib.Sysroot(sysroot_path)
305
306 if not chroot.exists():
307 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
Alex Klein231d2da2019-07-22 16:44:45 -0600308 elif not sysroot.Exists(chroot=chroot):
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600309 cros_build_lib.Die('Sysroot does not exist: %s',
310 chroot.full_path(sysroot.path))
311
312 pins = artifacts.FetchPinnedGuestImages(chroot, sysroot)
313
314 for pin in pins:
315 pinned_image = output_proto.pinned_images.add()
316 pinned_image.filename = pin.filename
317 pinned_image.uri = pin.uri
318
319
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700320def _BundleFirmwareResponse(input_proto, output_proto, _config):
321 """Add test firmware image files to a successful response."""
322 output_proto.artifacts.add().path = os.path.join(
323 input_proto.output_dir, 'firmware.tar.gz')
324
325
326@faux.success(_BundleFirmwareResponse)
327@faux.empty_error
Michael Mortensen38675192019-06-28 16:52:55 +0000328@validate.require('output_dir', 'sysroot.path')
Alex Klein231d2da2019-07-22 16:44:45 -0600329@validate.exists('output_dir')
330@validate.validation_complete
331def BundleFirmware(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600332 """Tar the firmware images for a build target.
333
334 Args:
335 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600336 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600337 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600338 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600339 output_dir = input_proto.output_dir
Michael Mortensen38675192019-06-28 16:52:55 +0000340 chroot = controller_util.ParseChroot(input_proto.chroot)
341 sysroot_path = input_proto.sysroot.path
342 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -0600343
344 if not chroot.exists():
345 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
346 elif not sysroot.Exists(chroot=chroot):
347 cros_build_lib.Die('Sysroot does not exist: %s',
348 chroot.full_path(sysroot.path))
349
Michael Mortensen38675192019-06-28 16:52:55 +0000350 archive = artifacts.BuildFirmwareArchive(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600351
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600352 if archive is None:
353 cros_build_lib.Die(
Michael Mortensen38675192019-06-28 16:52:55 +0000354 'Could not create firmware archive. No firmware found for %s.',
355 sysroot_path)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600356
Alex Klein231d2da2019-07-22 16:44:45 -0600357 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600358
359
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700360def _BundleEbuildLogsResponse(input_proto, output_proto, _config):
361 """Add test log files to a successful response."""
362 output_proto.artifacts.add().path = os.path.join(
363 input_proto.output_dir, 'ebuild-logs.tar.gz')
364
365
366@faux.success(_BundleEbuildLogsResponse)
367@faux.empty_error
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600368@validate.exists('output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600369def BundleEbuildLogs(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600370 """Tar the ebuild logs for a build target.
371
372 Args:
373 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600374 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600375 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600376 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600377 output_dir = input_proto.output_dir
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600378 sysroot_path = input_proto.sysroot.path
379 chroot = controller_util.ParseChroot(input_proto.chroot)
Evan Hernandeza478d802019-04-08 15:08:24 -0600380
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600381 # TODO(mmortensen) Cleanup legacy handling after it has been switched over.
382 target = input_proto.build_target.name
383 if target:
384 # Legacy handling.
385 build_root = constants.SOURCE_ROOT
Alex Klein171da612019-08-06 14:00:42 -0600386 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600387 sysroot_path = os.path.join('/build', target)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600388
Alex Klein231d2da2019-07-22 16:44:45 -0600389 # TODO(saklein): Switch to validation_complete decorator after legacy
390 # handling has been cleaned up.
391 if config.validate_only:
392 return controller.RETURN_CODE_VALID_INPUT
393
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600394 sysroot = sysroot_lib.Sysroot(sysroot_path)
395 archive = artifacts.BundleEBuildLogsTarball(chroot, sysroot, output_dir)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600396 if archive is None:
397 cros_build_lib.Die(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600398 'Could not create ebuild logs archive. No logs found for %s.',
399 sysroot.path)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600400 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600401
402
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700403def _BundleChromeOSConfigResponse(input_proto, output_proto, _config):
404 """Add test config files to a successful response."""
405 output_proto.artifacts.add().path = os.path.join(
406 input_proto.output_dir, 'config.yaml')
407
408
409@faux.success(_BundleChromeOSConfigResponse)
410@faux.empty_error
Andrew Lamb811aead2019-08-12 10:25:05 -0600411@validate.exists('output_dir')
412@validate.validation_complete
413def BundleChromeOSConfig(input_proto, output_proto, _config):
414 """Output the ChromeOS Config payload for a build target.
415
416 Args:
417 input_proto (BundleRequest): The input proto.
418 output_proto (BundleResponse): The output proto.
419 _config (api_config.ApiConfig): The API call config.
420 """
421 output_dir = input_proto.output_dir
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600422 sysroot_path = input_proto.sysroot.path
Andrew Lamb811aead2019-08-12 10:25:05 -0600423 chroot = controller_util.ParseChroot(input_proto.chroot)
424
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600425 # TODO(mmortensen) Cleanup legacy handling after it has been switched over.
426 target = input_proto.build_target.name
427 if target:
428 # Legacy handling.
429 build_root = constants.SOURCE_ROOT
430 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
431 sysroot_path = os.path.join('/build', target)
432
433 sysroot = sysroot_lib.Sysroot(sysroot_path)
Andrew Lamb811aead2019-08-12 10:25:05 -0600434 chromeos_config = artifacts.BundleChromeOSConfig(chroot, sysroot, output_dir)
435 if chromeos_config is None:
436 cros_build_lib.Die(
437 'Could not create ChromeOS Config payload. No config found for %s.',
438 sysroot.path)
439 output_proto.artifacts.add().path = os.path.join(output_dir, chromeos_config)
440
441
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700442def _BundleSimpleChromeArtifactsResponse(input_proto, output_proto, _config):
443 """Add test simple chrome files to a successful response."""
444 output_proto.artifacts.add().path = os.path.join(
445 input_proto.output_dir, 'simple_chrome.txt')
446
447
448@faux.success(_BundleSimpleChromeArtifactsResponse)
449@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600450@validate.require('output_dir', 'sysroot.build_target.name', 'sysroot.path')
451@validate.exists('output_dir')
452@validate.validation_complete
453def BundleSimpleChromeArtifacts(input_proto, output_proto, _config):
Alex Klein2275d692019-04-23 16:04:12 -0600454 """Create the simple chrome artifacts."""
455 # Required args.
456 sysroot_path = input_proto.sysroot.path
457 build_target_name = input_proto.sysroot.build_target.name
458 output_dir = input_proto.output_dir
459
Alex Klein2275d692019-04-23 16:04:12 -0600460 # Optional args.
461 chroot_path = input_proto.chroot.path or constants.DEFAULT_CHROOT_PATH
462 cache_dir = input_proto.chroot.cache_dir
463
464 # Build out the argument instances.
465 build_target = build_target_util.BuildTarget(build_target_name)
466 chroot = chroot_lib.Chroot(path=chroot_path, cache_dir=cache_dir)
467 # Sysroot.path needs to be the fully qualified path, including the chroot.
468 full_sysroot_path = os.path.join(chroot.path, sysroot_path.lstrip(os.sep))
469 sysroot = sysroot_lib.Sysroot(full_sysroot_path)
470
471 # Quick sanity check that the sysroot exists before we go on.
472 if not sysroot.Exists():
473 cros_build_lib.Die('The sysroot does not exist.')
474
475 try:
476 results = artifacts.BundleSimpleChromeArtifacts(chroot, sysroot,
477 build_target, output_dir)
478 except artifacts.Error as e:
479 cros_build_lib.Die('Error %s raised in BundleSimpleChromeArtifacts: %s',
480 type(e), e)
481
482 for file_name in results:
483 output_proto.artifacts.add().path = file_name
484
485
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700486def _BundleVmFilesResponse(input_proto, output_proto, _config):
487 """Add test vm files to a successful response."""
488 output_proto.artifacts.add().path = os.path.join(
489 input_proto.output_dir, 'f1.tar')
490
491
492@faux.success(_BundleVmFilesResponse)
493@faux.empty_error
Michael Mortensen51f06722019-07-18 09:55:50 -0600494@validate.require('chroot.path', 'test_results_dir', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600495@validate.exists('output_dir')
496@validate.validation_complete
497def BundleVmFiles(input_proto, output_proto, _config):
Alex Klein6504eca2019-04-18 15:37:56 -0600498 """Tar VM disk and memory files.
499
500 Args:
Trent Begin008cade2019-10-31 13:40:59 -0600501 input_proto (BundleVmFilesRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600502 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600503 _config (api_config.ApiConfig): The API call config.
Alex Klein6504eca2019-04-18 15:37:56 -0600504 """
Michael Mortensen51f06722019-07-18 09:55:50 -0600505 chroot = controller_util.ParseChroot(input_proto.chroot)
506 test_results_dir = input_proto.test_results_dir
Alex Klein6504eca2019-04-18 15:37:56 -0600507 output_dir = input_proto.output_dir
508
Michael Mortensen51f06722019-07-18 09:55:50 -0600509 archives = artifacts.BundleVmFiles(
510 chroot, test_results_dir, output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600511 for archive in archives:
512 output_proto.artifacts.add().path = archive
Tiancong Wangc4805b72019-06-11 12:12:03 -0700513
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700514def _BundleAFDOGenerationArtifactsResponse(input_proto, output_proto, _config):
515 """Add test tarball AFDO file to a successful response."""
516 output_proto.artifacts.add().path = os.path.join(
517 input_proto.output_dir, 'artifact1')
518
Alex Klein231d2da2019-07-22 16:44:45 -0600519
Tiancong Wang24a3df72019-08-20 15:48:51 -0700520_VALID_ARTIFACT_TYPES = [toolchain_pb2.BENCHMARK_AFDO,
521 toolchain_pb2.ORDERFILE]
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700522@faux.success(_BundleAFDOGenerationArtifactsResponse)
523@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600524@validate.require('build_target.name', 'output_dir')
Tiancong Wang50b80a92019-08-01 14:46:15 -0700525@validate.is_in('artifact_type', _VALID_ARTIFACT_TYPES)
Alex Klein231d2da2019-07-22 16:44:45 -0600526@validate.exists('output_dir')
Tiancong Wang2ade7932019-09-27 14:15:40 -0700527@validate.exists('chroot.chrome_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600528@validate.validation_complete
Tiancong Wang50b80a92019-08-01 14:46:15 -0700529def BundleAFDOGenerationArtifacts(input_proto, output_proto, _config):
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700530 """Generic function for creating tarballs of both AFDO and orderfile.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700531
532 Args:
Tiancong Wang50b80a92019-08-01 14:46:15 -0700533 input_proto (BundleChromeAFDORequest): The input proto.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700534 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600535 _config (api_config.ApiConfig): The API call config.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700536 """
Tiancong Wang50b80a92019-08-01 14:46:15 -0700537
Tiancong Wangc4805b72019-06-11 12:12:03 -0700538 # Required args.
Alex Klein231d2da2019-07-22 16:44:45 -0600539 build_target = build_target_util.BuildTarget(input_proto.build_target.name)
Tiancong Wang2ade7932019-09-27 14:15:40 -0700540 chrome_root = input_proto.chroot.chrome_dir
541 if not chrome_root:
542 cros_build_lib.Die('chrome_root is not included in chroot')
Tiancong Wangc4805b72019-06-11 12:12:03 -0700543 output_dir = input_proto.output_dir
Tiancong Wang50b80a92019-08-01 14:46:15 -0700544 artifact_type = input_proto.artifact_type
Tiancong Wangc4805b72019-06-11 12:12:03 -0700545
Tiancong Wangc4805b72019-06-11 12:12:03 -0700546 chroot = controller_util.ParseChroot(input_proto.chroot)
547
548 try:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700549 is_orderfile = bool(artifact_type is toolchain_pb2.ORDERFILE)
Tiancong Wang50b80a92019-08-01 14:46:15 -0700550 results = artifacts.BundleAFDOGenerationArtifacts(
Tiancong Wang2ade7932019-09-27 14:15:40 -0700551 is_orderfile, chroot, chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700552 build_target, output_dir)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700553 except artifacts.Error as e:
554 cros_build_lib.Die('Error %s raised in BundleSimpleChromeArtifacts: %s',
555 type(e), e)
556
557 for file_name in results:
558 output_proto.artifacts.add().path = file_name
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600559
560
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700561def _ExportCpeReportResponse(input_proto, output_proto, _config):
562 """Add test cpe results to a successful response."""
563 output_proto.artifacts.add().path = os.path.join(
564 input_proto.output_dir, 'cpe_report.txt')
565 output_proto.artifacts.add().path = os.path.join(
566 input_proto.output_dir, 'cpe_warnings.txt')
567
568
569@faux.success(_ExportCpeReportResponse)
570@faux.empty_error
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600571@validate.exists('output_dir')
572def ExportCpeReport(input_proto, output_proto, config):
573 """Export a CPE report.
574
575 Args:
576 input_proto (BundleRequest): The input proto.
577 output_proto (BundleResponse): The output proto.
578 config (api_config.ApiConfig): The API call config.
579 """
580 chroot = controller_util.ParseChroot(input_proto.chroot)
581 output_dir = input_proto.output_dir
582
583 if input_proto.build_target.name:
584 # Legacy handling - use the default sysroot path for the build target.
585 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
586 sysroot = sysroot_lib.Sysroot(build_target.root)
587 elif input_proto.sysroot.path:
588 sysroot = sysroot_lib.Sysroot(input_proto.sysroot.path)
589 else:
590 # TODO(saklein): Switch to validate decorators once legacy handling can be
591 # cleaned up.
592 cros_build_lib.Die('sysroot.path is required.')
593
594 if config.validate_only:
595 return controller.RETURN_CODE_VALID_INPUT
596
597 cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
598
599 output_proto.artifacts.add().path = cpe_result.report
600 output_proto.artifacts.add().path = cpe_result.warnings