blob: c7c0ccbf869f72e3b3e0ed11967e420026e675d9 [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
Alex Klein2275d692019-04-23 16:04:12 -060017from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060018from chromite.lib import constants
19from chromite.lib import cros_build_lib
Evan Hernandezde445982019-04-22 13:42:34 -060020from chromite.lib import cros_logging as logging
Alex Klein2275d692019-04-23 16:04:12 -060021from chromite.lib import sysroot_lib
22from chromite.service import artifacts
Evan Hernandezf388cbf2019-04-01 11:15:23 -060023
24
Evan Hernandez9f125ac2019-04-08 17:18:47 -060025def _GetImageDir(build_root, target):
26 """Return path containing images for the given build target.
27
Alex Kleine2612a02019-04-18 13:51:06 -060028 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
29
Evan Hernandez9f125ac2019-04-08 17:18:47 -060030 Args:
31 build_root (str): Path to checkout where build occurs.
32 target (str): Name of the build target.
33
34 Returns:
Alex Kleind2bf1462019-10-24 16:37:04 -060035 Path to the latest directory containing target images or None.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060036 """
37 image_dir = os.path.join(build_root, 'src/build/images', target, 'latest')
38 if not os.path.exists(image_dir):
Alex Kleind2bf1462019-10-24 16:37:04 -060039 logging.warning('Expected to find image output for target %s at %s, but '
40 'path does not exist', target, image_dir)
41 return None
42
Evan Hernandez9f125ac2019-04-08 17:18:47 -060043 return image_dir
44
45
Michael Mortensen2d6a2402019-11-26 13:40:40 -070046def _BundleImageArchivesResponse(input_proto, output_proto, _config):
47 """Add artifact paths to a successful response."""
48 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
49 'path0.tar.xz')
50 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
51 'path1.tar.xz')
52
53
54@faux.success(_BundleImageArchivesResponse)
55@faux.empty_error
Alex Kleind91e95a2019-09-17 10:39:02 -060056@validate.require('build_target.name')
57@validate.exists('output_dir')
58@validate.validation_complete
59def BundleImageArchives(input_proto, output_proto, _config):
60 """Create a .tar.xz archive for each image that has been created."""
61 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
62 output_dir = input_proto.output_dir
63 image_dir = _GetImageDir(constants.SOURCE_ROOT, build_target.name)
Alex Kleind2bf1462019-10-24 16:37:04 -060064 if image_dir is None:
65 return
Alex Kleind91e95a2019-09-17 10:39:02 -060066
67 archives = artifacts.ArchiveImages(image_dir, output_dir)
68
69 for archive in archives:
70 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
71
72
Michael Mortensen2d6a2402019-11-26 13:40:40 -070073def _BundleImageZipResponse(input_proto, output_proto, _config):
74 """Add artifact zip files to a successful response."""
75 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
76 'image.zip')
77
78
79@faux.success(_BundleImageZipResponse)
80@faux.empty_error
Michael Mortensen01910922019-07-24 14:48:10 -060081@validate.require('build_target.name', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -060082@validate.exists('output_dir')
83@validate.validation_complete
84def BundleImageZip(input_proto, output_proto, _config):
Evan Hernandez9f125ac2019-04-08 17:18:47 -060085 """Bundle image.zip.
86
87 Args:
88 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -060089 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -060090 _config (api_config.ApiConfig): The API call config.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060091 """
92 target = input_proto.build_target.name
93 output_dir = input_proto.output_dir
94 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
Alex Kleind2bf1462019-10-24 16:37:04 -060095 if image_dir is None:
96 return None
Alex Klein231d2da2019-07-22 16:44:45 -060097
Michael Mortensen01910922019-07-24 14:48:10 -060098 archive = artifacts.BundleImageZip(output_dir, image_dir)
Evan Hernandez9f125ac2019-04-08 17:18:47 -060099 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
100
101
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700102def _BundleTestUpdatePayloadsResponse(input_proto, output_proto, _config):
103 """Add test payload files to a successful response."""
104 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
105 'payload1.bin')
106
107
108@faux.success(_BundleTestUpdatePayloadsResponse)
109@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600110@validate.require('build_target.name', 'output_dir')
111@validate.exists('output_dir')
112@validate.validation_complete
113def BundleTestUpdatePayloads(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600114 """Generate minimal update payloads for the build target for testing.
115
116 Args:
117 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600118 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600119 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600120 """
121 target = input_proto.build_target.name
122 output_dir = input_proto.output_dir
123 build_root = constants.SOURCE_ROOT
124
125 # Use the first available image to create the update payload.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600126 img_dir = _GetImageDir(build_root, target)
Alex Kleind2bf1462019-10-24 16:37:04 -0600127 if img_dir is None:
128 return None
129
Alex Kleincb541e82019-06-26 15:06:11 -0600130 img_types = [constants.IMAGE_TYPE_TEST, constants.IMAGE_TYPE_DEV,
131 constants.IMAGE_TYPE_BASE]
132 img_names = [constants.IMAGE_TYPE_TO_NAME[t] for t in img_types]
Mike Frysinger66ce4132019-07-17 22:52:52 -0400133 img_paths = [os.path.join(img_dir, x) for x in img_names]
Mike Frysingera552be42018-08-17 14:39:32 -0400134 valid_images = [x for x in img_paths if os.path.exists(x)]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600135
Alex Kleincb541e82019-06-26 15:06:11 -0600136 if not valid_images:
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600137 cros_build_lib.Die(
138 'Expected to find an image of type among %r for target "%s" '
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600139 'at path %s.', img_types, target, img_dir)
Alex Kleincb541e82019-06-26 15:06:11 -0600140 image = valid_images[0]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600141
Alex Kleincb541e82019-06-26 15:06:11 -0600142 payloads = artifacts.BundleTestUpdatePayloads(image, output_dir)
143 for payload in payloads:
144 output_proto.artifacts.add().path = payload
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600145
146
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700147def _BundleAutotestFilesResponse(input_proto, output_proto, _config):
148 """Add test autotest files to a successful response."""
149 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
150 'autotest-a.tar.gz')
151
152
153@faux.success(_BundleAutotestFilesResponse)
154@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600155@validate.require('output_dir')
156@validate.exists('output_dir')
157def BundleAutotestFiles(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600158 """Tar the autotest files for a build target.
159
160 Args:
161 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600162 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600163 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600164 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600165 output_dir = input_proto.output_dir
Alex Klein238d8862019-05-07 11:32:46 -0600166 target = input_proto.build_target.name
Alex Kleine21a0952019-08-23 16:08:16 -0600167 chroot = controller_util.ParseChroot(input_proto.chroot)
168
Alex Klein238d8862019-05-07 11:32:46 -0600169 if target:
Alex Kleine21a0952019-08-23 16:08:16 -0600170 sysroot_path = os.path.join('/build', target)
Alex Klein238d8862019-05-07 11:32:46 -0600171 else:
172 # New style call, use chroot and sysroot.
Alex Klein238d8862019-05-07 11:32:46 -0600173 sysroot_path = input_proto.sysroot.path
174 if not sysroot_path:
175 cros_build_lib.Die('sysroot.path is required.')
176
Alex Kleine21a0952019-08-23 16:08:16 -0600177 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600178
Alex Klein231d2da2019-07-22 16:44:45 -0600179 # TODO(saklein): Switch to the validate_only decorator when legacy handling
180 # is removed.
181 if config.validate_only:
182 return controller.RETURN_CODE_VALID_INPUT
183
Alex Kleine21a0952019-08-23 16:08:16 -0600184 if not sysroot.Exists(chroot=chroot):
Alex Klein238d8862019-05-07 11:32:46 -0600185 cros_build_lib.Die('Sysroot path must exist: %s', sysroot.path)
186
187 try:
188 # Note that this returns the full path to *multiple* tarballs.
Alex Kleine21a0952019-08-23 16:08:16 -0600189 archives = artifacts.BundleAutotestFiles(chroot, sysroot, output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600190 except artifacts.Error as e:
Alex Klein03890312020-06-30 09:59:50 -0600191 logging.warning(e)
192 return
Alex Klein238d8862019-05-07 11:32:46 -0600193
194 for archive in archives.values():
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600195 output_proto.artifacts.add().path = archive
196
197
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700198def _BundleTastFilesResponse(input_proto, output_proto, _config):
199 """Add test tast files to a successful response."""
200 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
201 'tast_bundles.tar.gz')
202
203
204@faux.success(_BundleTastFilesResponse)
205@faux.empty_error
Alex Kleinb9d810b2019-07-01 12:38:02 -0600206@validate.require('output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600207@validate.exists('output_dir')
208def BundleTastFiles(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600209 """Tar the tast files for a build target.
210
211 Args:
212 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600213 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600214 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600215 """
216 target = input_proto.build_target.name
217 output_dir = input_proto.output_dir
218 build_root = constants.SOURCE_ROOT
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600219
Alex Kleinb9d810b2019-07-01 12:38:02 -0600220 chroot = controller_util.ParseChroot(input_proto.chroot)
221 sysroot_path = input_proto.sysroot.path
222
223 # TODO(saklein) Cleanup legacy handling after it has been switched over.
224 if target:
225 # Legacy handling.
Alex Klein171da612019-08-06 14:00:42 -0600226 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
Alex Kleinb9d810b2019-07-01 12:38:02 -0600227 sysroot_path = os.path.join('/build', target)
228
229 # New handling - chroot & sysroot based.
230 # TODO(saklein) Switch this to the require decorator when legacy is removed.
231 if not sysroot_path:
232 cros_build_lib.Die('sysroot.path is required.')
233
Alex Klein231d2da2019-07-22 16:44:45 -0600234 # TODO(saklein): Switch to the validation_complete decorator when legacy
235 # handling is removed.
236 if config.validate_only:
237 return controller.RETURN_CODE_VALID_INPUT
238
Alex Kleinb9d810b2019-07-01 12:38:02 -0600239 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -0600240 if not sysroot.Exists(chroot=chroot):
Alex Kleinb9d810b2019-07-01 12:38:02 -0600241 cros_build_lib.Die('Sysroot must exist.')
242
243 archive = artifacts.BundleTastFiles(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600244
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600245 if archive:
246 output_proto.artifacts.add().path = archive
247 else:
248 logging.warning('Found no tast files for %s.', target)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600249
250
Fergus Dall34d74e12020-09-29 15:52:32 +1000251def BundlePinnedGuestImages(_input_proto, _output_proto, _config):
252 # TODO(crbug/1034529): Remove this endpoint
253 pass
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700254
Fergus Dall34d74e12020-09-29 15:52:32 +1000255def FetchPinnedGuestImageUris(_input_proto, _output_proto, _config):
256 # TODO(crbug/1034529): Remove this endpoint
257 pass
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600258
259
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700260def _BundleFirmwareResponse(input_proto, output_proto, _config):
261 """Add test firmware image files to a successful response."""
262 output_proto.artifacts.add().path = os.path.join(
263 input_proto.output_dir, 'firmware.tar.gz')
264
265
266@faux.success(_BundleFirmwareResponse)
267@faux.empty_error
Michael Mortensen38675192019-06-28 16:52:55 +0000268@validate.require('output_dir', 'sysroot.path')
Alex Klein231d2da2019-07-22 16:44:45 -0600269@validate.exists('output_dir')
270@validate.validation_complete
271def BundleFirmware(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600272 """Tar the firmware images for a build target.
273
274 Args:
275 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600276 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600277 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600278 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600279 output_dir = input_proto.output_dir
Michael Mortensen38675192019-06-28 16:52:55 +0000280 chroot = controller_util.ParseChroot(input_proto.chroot)
281 sysroot_path = input_proto.sysroot.path
282 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -0600283
284 if not chroot.exists():
285 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
286 elif not sysroot.Exists(chroot=chroot):
287 cros_build_lib.Die('Sysroot does not exist: %s',
288 chroot.full_path(sysroot.path))
289
Michael Mortensen38675192019-06-28 16:52:55 +0000290 archive = artifacts.BuildFirmwareArchive(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600291
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600292 if archive is None:
293 cros_build_lib.Die(
Michael Mortensen38675192019-06-28 16:52:55 +0000294 'Could not create firmware archive. No firmware found for %s.',
295 sysroot_path)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600296
Alex Klein231d2da2019-07-22 16:44:45 -0600297 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600298
299
Yicheng Liea1181f2020-09-22 11:51:10 -0700300def _BundleFpmcuUnittestsResponse(input_proto, output_proto, _config):
301 """Add fingerprint MCU unittest binaries to a successful response."""
302 output_proto.artifacts.add().path = os.path.join(
303 input_proto.output_dir, 'fpmcu_unittests.tar.gz')
304
305
306@faux.success(_BundleFpmcuUnittestsResponse)
307@faux.empty_error
308@validate.require('output_dir', 'sysroot.path')
309@validate.exists('output_dir')
310@validate.validation_complete
311def BundleFpmcuUnittests(input_proto, output_proto, _config):
312 """Tar the fingerprint MCU unittest binaries for a build target.
313
314 Args:
315 input_proto (BundleRequest): The input proto.
316 output_proto (BundleResponse): The output proto.
317 _config (api_config.ApiConfig): The API call config.
318 """
319 output_dir = input_proto.output_dir
320 chroot = controller_util.ParseChroot(input_proto.chroot)
321 sysroot_path = input_proto.sysroot.path
322 sysroot = sysroot_lib.Sysroot(sysroot_path)
323
324 if not chroot.exists():
325 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
326 elif not sysroot.Exists(chroot=chroot):
327 cros_build_lib.Die('Sysroot does not exist: %s',
328 chroot.full_path(sysroot.path))
329
330 archive = artifacts.BundleFpmcuUnittests(chroot, sysroot, output_dir)
331
332 if archive is None:
333 logging.warning(
334 'No fpmcu unittests found for %s.', sysroot_path)
335 return
336
337 output_proto.artifacts.add().path = archive
338
339
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700340def _BundleEbuildLogsResponse(input_proto, output_proto, _config):
341 """Add test log files to a successful response."""
342 output_proto.artifacts.add().path = os.path.join(
343 input_proto.output_dir, 'ebuild-logs.tar.gz')
344
345
346@faux.success(_BundleEbuildLogsResponse)
347@faux.empty_error
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600348@validate.exists('output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600349def BundleEbuildLogs(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600350 """Tar the ebuild logs for a build target.
351
352 Args:
353 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600354 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600355 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600356 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600357 output_dir = input_proto.output_dir
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600358 sysroot_path = input_proto.sysroot.path
359 chroot = controller_util.ParseChroot(input_proto.chroot)
Evan Hernandeza478d802019-04-08 15:08:24 -0600360
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600361 # TODO(mmortensen) Cleanup legacy handling after it has been switched over.
362 target = input_proto.build_target.name
363 if target:
364 # Legacy handling.
365 build_root = constants.SOURCE_ROOT
Alex Klein171da612019-08-06 14:00:42 -0600366 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600367 sysroot_path = os.path.join('/build', target)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600368
Alex Klein231d2da2019-07-22 16:44:45 -0600369 # TODO(saklein): Switch to validation_complete decorator after legacy
370 # handling has been cleaned up.
371 if config.validate_only:
372 return controller.RETURN_CODE_VALID_INPUT
373
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600374 sysroot = sysroot_lib.Sysroot(sysroot_path)
375 archive = artifacts.BundleEBuildLogsTarball(chroot, sysroot, output_dir)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600376 if archive is None:
377 cros_build_lib.Die(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600378 'Could not create ebuild logs archive. No logs found for %s.',
379 sysroot.path)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600380 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600381
382
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700383def _BundleChromeOSConfigResponse(input_proto, output_proto, _config):
384 """Add test config files to a successful response."""
385 output_proto.artifacts.add().path = os.path.join(
386 input_proto.output_dir, 'config.yaml')
387
388
389@faux.success(_BundleChromeOSConfigResponse)
390@faux.empty_error
Andrew Lamb811aead2019-08-12 10:25:05 -0600391@validate.exists('output_dir')
392@validate.validation_complete
393def BundleChromeOSConfig(input_proto, output_proto, _config):
394 """Output the ChromeOS Config payload for a build target.
395
396 Args:
397 input_proto (BundleRequest): The input proto.
398 output_proto (BundleResponse): The output proto.
399 _config (api_config.ApiConfig): The API call config.
400 """
401 output_dir = input_proto.output_dir
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600402 sysroot_path = input_proto.sysroot.path
Andrew Lamb811aead2019-08-12 10:25:05 -0600403 chroot = controller_util.ParseChroot(input_proto.chroot)
404
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600405 # TODO(mmortensen) Cleanup legacy handling after it has been switched over.
406 target = input_proto.build_target.name
407 if target:
408 # Legacy handling.
409 build_root = constants.SOURCE_ROOT
410 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
411 sysroot_path = os.path.join('/build', target)
412
413 sysroot = sysroot_lib.Sysroot(sysroot_path)
Andrew Lamb811aead2019-08-12 10:25:05 -0600414 chromeos_config = artifacts.BundleChromeOSConfig(chroot, sysroot, output_dir)
415 if chromeos_config is None:
416 cros_build_lib.Die(
417 'Could not create ChromeOS Config payload. No config found for %s.',
418 sysroot.path)
419 output_proto.artifacts.add().path = os.path.join(output_dir, chromeos_config)
420
421
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700422def _BundleSimpleChromeArtifactsResponse(input_proto, output_proto, _config):
423 """Add test simple chrome files to a successful response."""
424 output_proto.artifacts.add().path = os.path.join(
425 input_proto.output_dir, 'simple_chrome.txt')
426
427
428@faux.success(_BundleSimpleChromeArtifactsResponse)
429@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600430@validate.require('output_dir', 'sysroot.build_target.name', 'sysroot.path')
431@validate.exists('output_dir')
432@validate.validation_complete
433def BundleSimpleChromeArtifacts(input_proto, output_proto, _config):
Alex Klein2275d692019-04-23 16:04:12 -0600434 """Create the simple chrome artifacts."""
Alex Klein2275d692019-04-23 16:04:12 -0600435 sysroot_path = input_proto.sysroot.path
Alex Klein2275d692019-04-23 16:04:12 -0600436 output_dir = input_proto.output_dir
437
Alex Klein2275d692019-04-23 16:04:12 -0600438 # Build out the argument instances.
Alex Klein26e472b2020-03-10 14:35:01 -0600439 build_target = controller_util.ParseBuildTarget(
440 input_proto.sysroot.build_target)
441 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein2275d692019-04-23 16:04:12 -0600442 # Sysroot.path needs to be the fully qualified path, including the chroot.
443 full_sysroot_path = os.path.join(chroot.path, sysroot_path.lstrip(os.sep))
444 sysroot = sysroot_lib.Sysroot(full_sysroot_path)
445
446 # Quick sanity check that the sysroot exists before we go on.
447 if not sysroot.Exists():
448 cros_build_lib.Die('The sysroot does not exist.')
449
450 try:
451 results = artifacts.BundleSimpleChromeArtifacts(chroot, sysroot,
452 build_target, output_dir)
453 except artifacts.Error as e:
454 cros_build_lib.Die('Error %s raised in BundleSimpleChromeArtifacts: %s',
455 type(e), e)
456
457 for file_name in results:
458 output_proto.artifacts.add().path = file_name
459
460
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700461def _BundleVmFilesResponse(input_proto, output_proto, _config):
462 """Add test vm files to a successful response."""
463 output_proto.artifacts.add().path = os.path.join(
464 input_proto.output_dir, 'f1.tar')
465
466
467@faux.success(_BundleVmFilesResponse)
468@faux.empty_error
Michael Mortensen51f06722019-07-18 09:55:50 -0600469@validate.require('chroot.path', 'test_results_dir', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600470@validate.exists('output_dir')
471@validate.validation_complete
472def BundleVmFiles(input_proto, output_proto, _config):
Alex Klein6504eca2019-04-18 15:37:56 -0600473 """Tar VM disk and memory files.
474
475 Args:
Trent Begin008cade2019-10-31 13:40:59 -0600476 input_proto (BundleVmFilesRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600477 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600478 _config (api_config.ApiConfig): The API call config.
Alex Klein6504eca2019-04-18 15:37:56 -0600479 """
Michael Mortensen51f06722019-07-18 09:55:50 -0600480 chroot = controller_util.ParseChroot(input_proto.chroot)
481 test_results_dir = input_proto.test_results_dir
Alex Klein6504eca2019-04-18 15:37:56 -0600482 output_dir = input_proto.output_dir
483
Michael Mortensen51f06722019-07-18 09:55:50 -0600484 archives = artifacts.BundleVmFiles(
485 chroot, test_results_dir, output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600486 for archive in archives:
487 output_proto.artifacts.add().path = archive
Tiancong Wangc4805b72019-06-11 12:12:03 -0700488
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700489def _BundleAFDOGenerationArtifactsResponse(input_proto, output_proto, _config):
490 """Add test tarball AFDO file to a successful response."""
491 output_proto.artifacts.add().path = os.path.join(
492 input_proto.output_dir, 'artifact1')
493
Alex Klein231d2da2019-07-22 16:44:45 -0600494
Tiancong Wang24a3df72019-08-20 15:48:51 -0700495_VALID_ARTIFACT_TYPES = [toolchain_pb2.BENCHMARK_AFDO,
496 toolchain_pb2.ORDERFILE]
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700497@faux.success(_BundleAFDOGenerationArtifactsResponse)
498@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600499@validate.require('build_target.name', 'output_dir')
Tiancong Wang50b80a92019-08-01 14:46:15 -0700500@validate.is_in('artifact_type', _VALID_ARTIFACT_TYPES)
Alex Klein231d2da2019-07-22 16:44:45 -0600501@validate.exists('output_dir')
Tiancong Wang2ade7932019-09-27 14:15:40 -0700502@validate.exists('chroot.chrome_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600503@validate.validation_complete
Tiancong Wang50b80a92019-08-01 14:46:15 -0700504def BundleAFDOGenerationArtifacts(input_proto, output_proto, _config):
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700505 """Generic function for creating tarballs of both AFDO and orderfile.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700506
507 Args:
Tiancong Wang50b80a92019-08-01 14:46:15 -0700508 input_proto (BundleChromeAFDORequest): The input proto.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700509 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600510 _config (api_config.ApiConfig): The API call config.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700511 """
Tiancong Wang2ade7932019-09-27 14:15:40 -0700512 chrome_root = input_proto.chroot.chrome_dir
Tiancong Wangc4805b72019-06-11 12:12:03 -0700513 output_dir = input_proto.output_dir
Tiancong Wang50b80a92019-08-01 14:46:15 -0700514 artifact_type = input_proto.artifact_type
Tiancong Wangc4805b72019-06-11 12:12:03 -0700515
Alex Klein26e472b2020-03-10 14:35:01 -0600516 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700517 chroot = controller_util.ParseChroot(input_proto.chroot)
518
519 try:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700520 is_orderfile = bool(artifact_type is toolchain_pb2.ORDERFILE)
Tiancong Wang50b80a92019-08-01 14:46:15 -0700521 results = artifacts.BundleAFDOGenerationArtifacts(
Tiancong Wang2ade7932019-09-27 14:15:40 -0700522 is_orderfile, chroot, chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700523 build_target, output_dir)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700524 except artifacts.Error as e:
525 cros_build_lib.Die('Error %s raised in BundleSimpleChromeArtifacts: %s',
526 type(e), e)
527
528 for file_name in results:
529 output_proto.artifacts.add().path = file_name
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600530
531
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700532def _ExportCpeReportResponse(input_proto, output_proto, _config):
533 """Add test cpe results to a successful response."""
534 output_proto.artifacts.add().path = os.path.join(
535 input_proto.output_dir, 'cpe_report.txt')
536 output_proto.artifacts.add().path = os.path.join(
537 input_proto.output_dir, 'cpe_warnings.txt')
538
539
540@faux.success(_ExportCpeReportResponse)
541@faux.empty_error
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600542@validate.exists('output_dir')
543def ExportCpeReport(input_proto, output_proto, config):
544 """Export a CPE report.
545
546 Args:
547 input_proto (BundleRequest): The input proto.
548 output_proto (BundleResponse): The output proto.
549 config (api_config.ApiConfig): The API call config.
550 """
551 chroot = controller_util.ParseChroot(input_proto.chroot)
552 output_dir = input_proto.output_dir
553
554 if input_proto.build_target.name:
555 # Legacy handling - use the default sysroot path for the build target.
556 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
557 sysroot = sysroot_lib.Sysroot(build_target.root)
558 elif input_proto.sysroot.path:
559 sysroot = sysroot_lib.Sysroot(input_proto.sysroot.path)
560 else:
561 # TODO(saklein): Switch to validate decorators once legacy handling can be
562 # cleaned up.
563 cros_build_lib.Die('sysroot.path is required.')
564
565 if config.validate_only:
566 return controller.RETURN_CODE_VALID_INPUT
567
568 cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
569
570 output_proto.artifacts.add().path = cpe_result.report
571 output_proto.artifacts.add().path = cpe_result.warnings
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900572
573
574def _BundleGceTarballResponse(input_proto, output_proto, _config):
575 """Add artifact tarball to a successful response."""
576 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
577 constants.TEST_IMAGE_GCE_TAR)
578
579
580@faux.success(_BundleGceTarballResponse)
581@faux.empty_error
582@validate.require('build_target.name', 'output_dir')
583@validate.exists('output_dir')
584@validate.validation_complete
585def BundleGceTarball(input_proto, output_proto, _config):
586 """Bundle the test image into a tarball suitable for importing into GCE.
587
588 Args:
589 input_proto (BundleRequest): The input proto.
590 output_proto (BundleResponse): The output proto.
591 _config (api_config.ApiConfig): The API call config.
592 """
593 target = input_proto.build_target.name
594 output_dir = input_proto.output_dir
595 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
596 if image_dir is None:
597 return None
598
599 tarball = artifacts.BundleGceTarball(output_dir, image_dir)
600 output_proto.artifacts.add().path = tarball