blob: 372f3f5218682330afd556af8b1eb103694426d2 [file] [log] [blame]
Evan Hernandezf388cbf2019-04-01 11:15:23 -06001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Implements ArtifactService."""
6
Chris McDonald1672ddb2021-07-21 11:48:23 -06007import logging
Evan Hernandezf388cbf2019-04-01 11:15:23 -06008import os
Varun Somani04dccd72021-10-09 01:06:11 +00009from typing import Any, NamedTuple, Optional, TYPE_CHECKING
Evan Hernandezf388cbf2019-04-01 11:15:23 -060010
Alex Klein231d2da2019-07-22 16:44:45 -060011from chromite.api import controller
Alex Klein076841b2019-08-29 15:19:39 -060012from chromite.api import faux
Alex Klein2b236722019-06-19 15:44:26 -060013from chromite.api import validate
Alex Klein238d8862019-05-07 11:32:46 -060014from chromite.api.controller import controller_util
George Engelbrechtc9a8e812021-06-16 18:14:17 -060015from chromite.api.controller import image as image_controller
16from chromite.api.controller import sysroot as sysroot_controller
David Wellingc1433c22021-06-25 16:29:48 +000017from chromite.api.controller import test as test_controller
LaMont Jones58362a42021-02-04 17:40:08 -070018from chromite.api.gen.chromite.api import artifacts_pb2
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000019from chromite.api.gen.chromiumos import common_pb2
Alex Klein2275d692019-04-23 16:04:12 -060020from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060021from chromite.lib import constants
22from chromite.lib import cros_build_lib
Alex Klein2275d692019-04-23 16:04:12 -060023from chromite.lib import sysroot_lib
24from chromite.service import artifacts
Greg Edelstondc941072021-08-11 12:32:30 -060025from chromite.service import test
Evan Hernandezf388cbf2019-04-01 11:15:23 -060026
Mike Frysinger1cc8f1f2022-04-28 22:40:40 -040027
Varun Somani04dccd72021-10-09 01:06:11 +000028if TYPE_CHECKING:
29 from chromite.api import api_config
Evan Hernandezf388cbf2019-04-01 11:15:23 -060030
George Engelbrechtc9a8e812021-06-16 18:14:17 -060031class RegisteredGet(NamedTuple):
32 """An registered function for calling Get on an artifact type."""
33 output_proto: artifacts_pb2.GetResponse
34 artifact_dict: Any
LaMont Jones0f5171b2021-01-29 12:28:56 -070035
36
George Engelbrechtc9a8e812021-06-16 18:14:17 -060037def ExampleGetResponse(_input_proto, _output_proto, _config):
38 """Give an example GetResponse with a minimal coverage set."""
39 _output_proto = artifacts_pb2.GetResponse(
40 artifacts=common_pb2.UploadedArtifactsByService(
41 image=image_controller.ExampleGetResponse(),
42 sysroot=sysroot_controller.ExampleGetResponse(),
43 ))
44 return controller.RETURN_CODE_SUCCESS
45
46
LaMont Jones0f5171b2021-01-29 12:28:56 -070047@faux.empty_error
George Engelbrechtc9a8e812021-06-16 18:14:17 -060048@faux.success(ExampleGetResponse)
LaMont Jones0f5171b2021-01-29 12:28:56 -070049@validate.exists('result_path.path.path')
50@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +000051def Get(
52 input_proto: artifacts_pb2.GetRequest,
53 output_proto: artifacts_pb2.GetResponse,
54 _config: 'api_config.ApiConfig'):
LaMont Jones0f5171b2021-01-29 12:28:56 -070055 """Get all artifacts.
56
57 Get all artifacts for the build.
58
George Engelbrechtc9a8e812021-06-16 18:14:17 -060059 Note: As the individual artifact_type bundlers are added here, they *must*
60 stop uploading it via the individual bundler function.
LaMont Jones0f5171b2021-01-29 12:28:56 -070061
62 Args:
Varun Somani04dccd72021-10-09 01:06:11 +000063 input_proto: The input proto.
64 output_proto: The output proto.
65 _config: The API call config.
LaMont Jones0f5171b2021-01-29 12:28:56 -070066 """
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000067 output_dir = input_proto.result_path.path.path
68
George Engelbrechtc9a8e812021-06-16 18:14:17 -060069 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
LaMont Jones8b88e9d2021-06-28 16:37:34 -060070 # This endpoint does not currently support any artifacts that are built
71 # without a sysroot being present.
72 if not sysroot.path:
73 return controller.RETURN_CODE_SUCCESS
74
George Engelbrechtc9a8e812021-06-16 18:14:17 -060075 chroot = controller_util.ParseChroot(input_proto.chroot)
76 build_target = controller_util.ParseBuildTarget(
77 input_proto.sysroot.build_target)
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000078
George Engelbrechtc9a8e812021-06-16 18:14:17 -060079 # A list of RegisteredGet tuples (input proto, output proto, get results).
80 get_res_list = [
81 RegisteredGet(
82 output_proto.artifacts.image,
83 image_controller.GetArtifacts(
84 input_proto.artifact_info.image, chroot, sysroot, build_target,
85 output_dir)),
86 RegisteredGet(
87 output_proto.artifacts.sysroot,
88 sysroot_controller.GetArtifacts(
89 input_proto.artifact_info.sysroot, chroot, sysroot, build_target,
David Wellingc1433c22021-06-25 16:29:48 +000090 output_dir)),
91 RegisteredGet(
92 output_proto.artifacts.test,
93 test_controller.GetArtifacts(
Jack Neusc9707c32021-07-23 21:48:54 +000094 input_proto.artifact_info.test, chroot, sysroot, build_target,
95 output_dir)),
George Engelbrechtc9a8e812021-06-16 18:14:17 -060096 ]
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000097
George Engelbrechtc9a8e812021-06-16 18:14:17 -060098 for get_res in get_res_list:
99 for artifact_dict in get_res.artifact_dict:
100 get_res.output_proto.artifacts.add(
101 artifact_type=artifact_dict['type'],
102 paths=[
103 common_pb2.Path(
104 path=x, location=common_pb2.Path.Location.OUTSIDE)
105 for x in artifact_dict['paths']
106 ])
LaMont Jones0f5171b2021-01-29 12:28:56 -0700107 return controller.RETURN_CODE_SUCCESS
108
109
LaMont Jones58362a42021-02-04 17:40:08 -0700110def _BuildSetupResponse(_input_proto, output_proto, _config):
111 """Just return POINTLESS for now."""
112 # All of the artifact types we support claim that the build is POINTLESS.
113 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
114
115
116@faux.success(_BuildSetupResponse)
117@faux.empty_error
118@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000119def BuildSetup(
120 _input_proto: artifacts_pb2.GetRequest,
121 output_proto: artifacts_pb2.GetResponse,
122 _config: 'api_config.ApiConfig'):
123
LaMont Jones58362a42021-02-04 17:40:08 -0700124 """Setup anything needed for building artifacts
125
126 If any artifact types require steps prior to building the package, they go
127 here. For example, see ToolchainService/PrepareForBuild.
128
129 Note: crbug/1034529 introduces this method as a noop. As the individual
130 artifact_type bundlers are added here, they *must* stop uploading it via the
131 individual bundler function.
132
133 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000134 _input_proto: The input proto.
135 output_proto: The output proto.
136 _config: The API call config.
LaMont Jones58362a42021-02-04 17:40:08 -0700137 """
138 # If any artifact_type says "NEEDED", the return is NEEDED.
139 # Otherwise, if any artifact_type says "UNKNOWN", the return is UNKNOWN.
140 # Otherwise, the return is POINTLESS.
141 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
142 return controller.RETURN_CODE_SUCCESS
143
144
Varun Somani04dccd72021-10-09 01:06:11 +0000145def _GetImageDir(build_root: str, target: str) -> Optional[str]:
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600146 """Return path containing images for the given build target.
147
Alex Kleine2612a02019-04-18 13:51:06 -0600148 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
149
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600150 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000151 build_root: Path to checkout where build occurs.
152 target: Name of the build target.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600153
154 Returns:
Alex Kleind2bf1462019-10-24 16:37:04 -0600155 Path to the latest directory containing target images or None.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600156 """
157 image_dir = os.path.join(build_root, 'src/build/images', target, 'latest')
158 if not os.path.exists(image_dir):
Alex Kleind2bf1462019-10-24 16:37:04 -0600159 logging.warning('Expected to find image output for target %s at %s, but '
160 'path does not exist', target, image_dir)
161 return None
162
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600163 return image_dir
164
165
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700166def _BundleImageArchivesResponse(input_proto, output_proto, _config):
167 """Add artifact paths to a successful response."""
168 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
169 'path0.tar.xz')
170 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
171 'path1.tar.xz')
172
173
174@faux.success(_BundleImageArchivesResponse)
175@faux.empty_error
Alex Kleind91e95a2019-09-17 10:39:02 -0600176@validate.require('build_target.name')
177@validate.exists('output_dir')
178@validate.validation_complete
179def BundleImageArchives(input_proto, output_proto, _config):
180 """Create a .tar.xz archive for each image that has been created."""
181 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
182 output_dir = input_proto.output_dir
183 image_dir = _GetImageDir(constants.SOURCE_ROOT, build_target.name)
Alex Kleind2bf1462019-10-24 16:37:04 -0600184 if image_dir is None:
185 return
Alex Kleind91e95a2019-09-17 10:39:02 -0600186
187 archives = artifacts.ArchiveImages(image_dir, output_dir)
188
189 for archive in archives:
190 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
191
192
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700193def _BundleImageZipResponse(input_proto, output_proto, _config):
194 """Add artifact zip files to a successful response."""
195 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
196 'image.zip')
197
198
199@faux.success(_BundleImageZipResponse)
200@faux.empty_error
Michael Mortensen01910922019-07-24 14:48:10 -0600201@validate.require('build_target.name', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600202@validate.exists('output_dir')
203@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000204def BundleImageZip(
205 input_proto: artifacts_pb2.BundleRequest,
206 output_proto: artifacts_pb2.BundleResponse,
207 _config: 'api_config.ApiConfig'):
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600208 """Bundle image.zip.
209
210 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000211 input_proto: The input proto.
212 output_proto: The output proto.
213 _config: The API call config.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600214 """
215 target = input_proto.build_target.name
216 output_dir = input_proto.output_dir
217 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
Alex Kleind2bf1462019-10-24 16:37:04 -0600218 if image_dir is None:
219 return None
Alex Klein231d2da2019-07-22 16:44:45 -0600220
Michael Mortensen01910922019-07-24 14:48:10 -0600221 archive = artifacts.BundleImageZip(output_dir, image_dir)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600222 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
223
224
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700225def _BundleTestUpdatePayloadsResponse(input_proto, output_proto, _config):
226 """Add test payload files to a successful response."""
227 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
228 'payload1.bin')
George Engelbrechtf0239d52022-04-06 13:09:33 -0600229 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
230 'payload1.json')
231 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
232 'payload1.log')
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700233
234
235@faux.success(_BundleTestUpdatePayloadsResponse)
236@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600237@validate.require('build_target.name', 'output_dir')
238@validate.exists('output_dir')
239@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000240def BundleTestUpdatePayloads(
241 input_proto: artifacts_pb2.BundleRequest,
242 output_proto: artifacts_pb2.BundleResponse,
243 _config: 'api_config.ApiConfig'):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600244 """Generate minimal update payloads for the build target for testing.
245
246 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000247 input_proto: The input proto.
248 output_proto: The output proto.
249 _config: The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600250 """
251 target = input_proto.build_target.name
252 output_dir = input_proto.output_dir
253 build_root = constants.SOURCE_ROOT
254
255 # Use the first available image to create the update payload.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600256 img_dir = _GetImageDir(build_root, target)
Alex Kleind2bf1462019-10-24 16:37:04 -0600257 if img_dir is None:
258 return None
259
Alex Kleincb541e82019-06-26 15:06:11 -0600260 img_types = [constants.IMAGE_TYPE_TEST, constants.IMAGE_TYPE_DEV,
261 constants.IMAGE_TYPE_BASE]
262 img_names = [constants.IMAGE_TYPE_TO_NAME[t] for t in img_types]
Mike Frysinger66ce4132019-07-17 22:52:52 -0400263 img_paths = [os.path.join(img_dir, x) for x in img_names]
Mike Frysingera552be42018-08-17 14:39:32 -0400264 valid_images = [x for x in img_paths if os.path.exists(x)]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600265
Alex Kleincb541e82019-06-26 15:06:11 -0600266 if not valid_images:
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600267 cros_build_lib.Die(
268 'Expected to find an image of type among %r for target "%s" '
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600269 'at path %s.', img_types, target, img_dir)
Alex Kleincb541e82019-06-26 15:06:11 -0600270 image = valid_images[0]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600271
Alex Kleincb541e82019-06-26 15:06:11 -0600272 payloads = artifacts.BundleTestUpdatePayloads(image, output_dir)
273 for payload in payloads:
274 output_proto.artifacts.add().path = payload
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600275
276
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700277def _BundleAutotestFilesResponse(input_proto, output_proto, _config):
278 """Add test autotest files to a successful response."""
279 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
280 'autotest-a.tar.gz')
281
282
283@faux.success(_BundleAutotestFilesResponse)
284@faux.empty_error
Alex Klein036833d2022-06-01 13:05:01 -0600285@validate.require('sysroot.path')
Alex Klein231d2da2019-07-22 16:44:45 -0600286@validate.exists('output_dir')
Alex Klein036833d2022-06-01 13:05:01 -0600287@validate.validation_complete
288def BundleAutotestFiles(input_proto: artifacts_pb2.BundleRequest,
289 output_proto: artifacts_pb2.BundleResponse,
290 _config: 'api_config.ApiConfig') -> None:
291 """Tar the autotest files for a build target."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600292 output_dir = input_proto.output_dir
Alex Kleine21a0952019-08-23 16:08:16 -0600293 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein036833d2022-06-01 13:05:01 -0600294 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600295
Alex Kleine21a0952019-08-23 16:08:16 -0600296 if not sysroot.Exists(chroot=chroot):
Alex Klein036833d2022-06-01 13:05:01 -0600297 logging.warning('Sysroot does not exist: %s', sysroot.path)
298 return
Alex Klein238d8862019-05-07 11:32:46 -0600299
300 try:
301 # Note that this returns the full path to *multiple* tarballs.
Alex Kleine21a0952019-08-23 16:08:16 -0600302 archives = artifacts.BundleAutotestFiles(chroot, sysroot, output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600303 except artifacts.Error as e:
Alex Klein03890312020-06-30 09:59:50 -0600304 logging.warning(e)
305 return
Alex Klein238d8862019-05-07 11:32:46 -0600306
307 for archive in archives.values():
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600308 output_proto.artifacts.add().path = archive
309
310
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700311def _BundleTastFilesResponse(input_proto, output_proto, _config):
312 """Add test tast files to a successful response."""
313 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
314 'tast_bundles.tar.gz')
315
316
317@faux.success(_BundleTastFilesResponse)
318@faux.empty_error
Alex Klein036833d2022-06-01 13:05:01 -0600319@validate.require('sysroot.path')
Alex Klein231d2da2019-07-22 16:44:45 -0600320@validate.exists('output_dir')
Alex Klein036833d2022-06-01 13:05:01 -0600321@validate.validation_complete
322def BundleTastFiles(input_proto: artifacts_pb2.BundleRequest,
323 output_proto: artifacts_pb2.BundleResponse,
324 _config: 'api_config.ApiConfig') -> None:
325 """Tar the tast files for a build target."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600326 output_dir = input_proto.output_dir
Alex Kleinb9d810b2019-07-01 12:38:02 -0600327 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein036833d2022-06-01 13:05:01 -0600328 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600329
Alex Klein231d2da2019-07-22 16:44:45 -0600330 if not sysroot.Exists(chroot=chroot):
Alex Klein036833d2022-06-01 13:05:01 -0600331 logging.warning('Sysroot does not exist: %s', sysroot.path)
332 return
Alex Kleinb9d810b2019-07-01 12:38:02 -0600333
334 archive = artifacts.BundleTastFiles(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600335
Alex Klein036833d2022-06-01 13:05:01 -0600336 if not archive:
337 logging.warning('Found no tast files for %s.', sysroot.path)
338 return
339
340 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600341
342
Fergus Dall34d74e12020-09-29 15:52:32 +1000343def BundlePinnedGuestImages(_input_proto, _output_proto, _config):
344 # TODO(crbug/1034529): Remove this endpoint
345 pass
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700346
Fergus Dall34d74e12020-09-29 15:52:32 +1000347def FetchPinnedGuestImageUris(_input_proto, _output_proto, _config):
348 # TODO(crbug/1034529): Remove this endpoint
349 pass
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600350
351
Greg Edelstondc941072021-08-11 12:32:30 -0600352def _FetchMetadataResponse(_input_proto, output_proto, _config):
353 """Populate the output_proto with sample data."""
354 for fp in ('/metadata/foo.txt', '/metadata/bar.jsonproto'):
355 output_proto.filepaths.add(path=common_pb2.Path(
356 path=fp, location=common_pb2.Path.OUTSIDE))
357 return controller.RETURN_CODE_SUCCESS
358
359
360@faux.success(_FetchMetadataResponse)
361@faux.empty_error
362@validate.exists('chroot.path')
363@validate.require('sysroot.path')
364@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000365def FetchMetadata(
366 input_proto: artifacts_pb2.FetchMetadataRequest,
367 output_proto: artifacts_pb2.FetchMetadataResponse,
368 _config: 'api_config.ApiConfig'):
Greg Edelstondc941072021-08-11 12:32:30 -0600369 """FetchMetadata returns the paths to all build/test metadata files.
370
371 This implements ArtifactsService.FetchMetadata.
372
373 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000374 input_proto: The input proto.
375 output_proto: The output proto.
376 config: The API call config.
Greg Edelstondc941072021-08-11 12:32:30 -0600377 """
378 chroot = controller_util.ParseChroot(input_proto.chroot)
379 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
380 for path in test.FindAllMetadataFiles(chroot, sysroot):
381 output_proto.filepaths.add(
382 path=common_pb2.Path(path=path, location=common_pb2.Path.OUTSIDE))
383 return controller.RETURN_CODE_SUCCESS
384
385
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700386def _BundleFirmwareResponse(input_proto, output_proto, _config):
387 """Add test firmware image files to a successful response."""
388 output_proto.artifacts.add().path = os.path.join(
389 input_proto.output_dir, 'firmware.tar.gz')
390
391
392@faux.success(_BundleFirmwareResponse)
393@faux.empty_error
Michael Mortensen38675192019-06-28 16:52:55 +0000394@validate.require('output_dir', 'sysroot.path')
Alex Klein231d2da2019-07-22 16:44:45 -0600395@validate.exists('output_dir')
396@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000397def BundleFirmware(
398 input_proto: artifacts_pb2.BundleRequest,
399 output_proto: artifacts_pb2.BundleResponse,
400 _config: 'api_config.ApiConfig'):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600401 """Tar the firmware images for a build target.
402
403 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000404 input_proto: The input proto.
405 output_proto: The output proto.
406 _config: The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600407 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600408 output_dir = input_proto.output_dir
Michael Mortensen38675192019-06-28 16:52:55 +0000409 chroot = controller_util.ParseChroot(input_proto.chroot)
410 sysroot_path = input_proto.sysroot.path
411 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -0600412
413 if not chroot.exists():
414 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
415 elif not sysroot.Exists(chroot=chroot):
416 cros_build_lib.Die('Sysroot does not exist: %s',
417 chroot.full_path(sysroot.path))
418
Michael Mortensen38675192019-06-28 16:52:55 +0000419 archive = artifacts.BuildFirmwareArchive(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600420
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600421 if archive is None:
George Engelbrecht9e41e172021-11-18 17:04:22 -0700422 logging.warning(
Michael Mortensen38675192019-06-28 16:52:55 +0000423 'Could not create firmware archive. No firmware found for %s.',
424 sysroot_path)
George Engelbrecht9e41e172021-11-18 17:04:22 -0700425 return
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600426
Alex Klein231d2da2019-07-22 16:44:45 -0600427 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600428
429
Yicheng Liea1181f2020-09-22 11:51:10 -0700430def _BundleFpmcuUnittestsResponse(input_proto, output_proto, _config):
431 """Add fingerprint MCU unittest binaries to a successful response."""
432 output_proto.artifacts.add().path = os.path.join(
433 input_proto.output_dir, 'fpmcu_unittests.tar.gz')
434
435
436@faux.success(_BundleFpmcuUnittestsResponse)
437@faux.empty_error
438@validate.require('output_dir', 'sysroot.path')
439@validate.exists('output_dir')
440@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000441def BundleFpmcuUnittests(
442 input_proto: artifacts_pb2.BundleRequest,
443 output_proto: artifacts_pb2.BundleResponse,
444 _config: 'api_config.ApiConfig'):
Yicheng Liea1181f2020-09-22 11:51:10 -0700445 """Tar the fingerprint MCU unittest binaries for a build target.
446
447 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000448 input_proto: The input proto.
449 output_proto: The output proto.
450 _config: The API call config.
Yicheng Liea1181f2020-09-22 11:51:10 -0700451 """
452 output_dir = input_proto.output_dir
453 chroot = controller_util.ParseChroot(input_proto.chroot)
454 sysroot_path = input_proto.sysroot.path
455 sysroot = sysroot_lib.Sysroot(sysroot_path)
456
457 if not chroot.exists():
458 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
459 elif not sysroot.Exists(chroot=chroot):
460 cros_build_lib.Die('Sysroot does not exist: %s',
461 chroot.full_path(sysroot.path))
462
463 archive = artifacts.BundleFpmcuUnittests(chroot, sysroot, output_dir)
464
465 if archive is None:
466 logging.warning(
467 'No fpmcu unittests found for %s.', sysroot_path)
468 return
469
470 output_proto.artifacts.add().path = archive
471
472
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700473def _BundleEbuildLogsResponse(input_proto, output_proto, _config):
474 """Add test log files to a successful response."""
475 output_proto.artifacts.add().path = os.path.join(
476 input_proto.output_dir, 'ebuild-logs.tar.gz')
477
478
479@faux.success(_BundleEbuildLogsResponse)
480@faux.empty_error
Alex Klein036833d2022-06-01 13:05:01 -0600481@validate.require('sysroot.path')
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600482@validate.exists('output_dir')
Alex Klein036833d2022-06-01 13:05:01 -0600483@validate.validation_complete
484def BundleEbuildLogs(input_proto: artifacts_pb2.BundleRequest,
485 output_proto: artifacts_pb2.BundleResponse,
486 _config: 'api_config.ApiConfig') -> None:
487 """Tar the ebuild logs for a build target."""
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600488 output_dir = input_proto.output_dir
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600489 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein036833d2022-06-01 13:05:01 -0600490 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Evan Hernandeza478d802019-04-08 15:08:24 -0600491
Alex Klein036833d2022-06-01 13:05:01 -0600492 if not sysroot.Exists(chroot=chroot):
493 logging.warning('Sysroot does not exist: %s', sysroot.path)
494 return
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600495
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600496 archive = artifacts.BundleEBuildLogsTarball(chroot, sysroot, output_dir)
Alex Klein036833d2022-06-01 13:05:01 -0600497
498 if not archive:
499 logging.warning(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600500 'Could not create ebuild logs archive. No logs found for %s.',
501 sysroot.path)
Alex Klein036833d2022-06-01 13:05:01 -0600502 return
503
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600504 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600505
506
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700507def _BundleChromeOSConfigResponse(input_proto, output_proto, _config):
508 """Add test config files to a successful response."""
509 output_proto.artifacts.add().path = os.path.join(
510 input_proto.output_dir, 'config.yaml')
511
512
513@faux.success(_BundleChromeOSConfigResponse)
514@faux.empty_error
Andrew Lamb811aead2019-08-12 10:25:05 -0600515@validate.exists('output_dir')
516@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000517def BundleChromeOSConfig(
518 input_proto: artifacts_pb2.BundleRequest,
519 output_proto: artifacts_pb2.BundleResponse,
520 _config: 'api_config.ApiConfig'):
Andrew Lamb811aead2019-08-12 10:25:05 -0600521 """Output the ChromeOS Config payload for a build target.
522
523 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000524 input_proto: The input proto.
525 output_proto: The output proto.
526 _config: The API call config.
Andrew Lamb811aead2019-08-12 10:25:05 -0600527 """
528 output_dir = input_proto.output_dir
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600529 sysroot_path = input_proto.sysroot.path
Andrew Lamb811aead2019-08-12 10:25:05 -0600530 chroot = controller_util.ParseChroot(input_proto.chroot)
531
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600532 # TODO(mmortensen) Cleanup legacy handling after it has been switched over.
533 target = input_proto.build_target.name
534 if target:
535 # Legacy handling.
536 build_root = constants.SOURCE_ROOT
537 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
538 sysroot_path = os.path.join('/build', target)
539
540 sysroot = sysroot_lib.Sysroot(sysroot_path)
Andrew Lamb811aead2019-08-12 10:25:05 -0600541 chromeos_config = artifacts.BundleChromeOSConfig(chroot, sysroot, output_dir)
Alex Klein383a7a32021-12-07 16:01:19 -0700542 if not chromeos_config:
543 return
544
Andrew Lamb811aead2019-08-12 10:25:05 -0600545 output_proto.artifacts.add().path = os.path.join(output_dir, chromeos_config)
546
547
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700548def _BundleSimpleChromeArtifactsResponse(input_proto, output_proto, _config):
549 """Add test simple chrome files to a successful response."""
550 output_proto.artifacts.add().path = os.path.join(
551 input_proto.output_dir, 'simple_chrome.txt')
552
553
554@faux.success(_BundleSimpleChromeArtifactsResponse)
555@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600556@validate.require('output_dir', 'sysroot.build_target.name', 'sysroot.path')
557@validate.exists('output_dir')
558@validate.validation_complete
559def BundleSimpleChromeArtifacts(input_proto, output_proto, _config):
Alex Klein2275d692019-04-23 16:04:12 -0600560 """Create the simple chrome artifacts."""
Alex Klein2275d692019-04-23 16:04:12 -0600561 sysroot_path = input_proto.sysroot.path
Alex Klein2275d692019-04-23 16:04:12 -0600562 output_dir = input_proto.output_dir
563
Alex Klein2275d692019-04-23 16:04:12 -0600564 # Build out the argument instances.
Alex Klein26e472b2020-03-10 14:35:01 -0600565 build_target = controller_util.ParseBuildTarget(
566 input_proto.sysroot.build_target)
567 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein2275d692019-04-23 16:04:12 -0600568 # Sysroot.path needs to be the fully qualified path, including the chroot.
569 full_sysroot_path = os.path.join(chroot.path, sysroot_path.lstrip(os.sep))
570 sysroot = sysroot_lib.Sysroot(full_sysroot_path)
571
572 # Quick sanity check that the sysroot exists before we go on.
573 if not sysroot.Exists():
574 cros_build_lib.Die('The sysroot does not exist.')
575
576 try:
577 results = artifacts.BundleSimpleChromeArtifacts(chroot, sysroot,
578 build_target, output_dir)
579 except artifacts.Error as e:
580 cros_build_lib.Die('Error %s raised in BundleSimpleChromeArtifacts: %s',
581 type(e), e)
582
583 for file_name in results:
584 output_proto.artifacts.add().path = file_name
585
586
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700587def _BundleVmFilesResponse(input_proto, output_proto, _config):
588 """Add test vm files to a successful response."""
589 output_proto.artifacts.add().path = os.path.join(
590 input_proto.output_dir, 'f1.tar')
591
592
593@faux.success(_BundleVmFilesResponse)
594@faux.empty_error
Michael Mortensen51f06722019-07-18 09:55:50 -0600595@validate.require('chroot.path', 'test_results_dir', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600596@validate.exists('output_dir')
597@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000598def BundleVmFiles(
599 input_proto: artifacts_pb2.BundleVmFilesRequest,
600 output_proto: artifacts_pb2.BundleResponse,
601 _config: 'api_config.ApiConfig'):
Alex Klein6504eca2019-04-18 15:37:56 -0600602 """Tar VM disk and memory files.
603
604 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000605 input_proto: The input proto.
606 output_proto: The output proto.
607 _config: The API call config.
Alex Klein6504eca2019-04-18 15:37:56 -0600608 """
Michael Mortensen51f06722019-07-18 09:55:50 -0600609 chroot = controller_util.ParseChroot(input_proto.chroot)
610 test_results_dir = input_proto.test_results_dir
Alex Klein6504eca2019-04-18 15:37:56 -0600611 output_dir = input_proto.output_dir
612
Michael Mortensen51f06722019-07-18 09:55:50 -0600613 archives = artifacts.BundleVmFiles(
614 chroot, test_results_dir, output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600615 for archive in archives:
616 output_proto.artifacts.add().path = archive
Tiancong Wangc4805b72019-06-11 12:12:03 -0700617
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700618def _ExportCpeReportResponse(input_proto, output_proto, _config):
619 """Add test cpe results to a successful response."""
620 output_proto.artifacts.add().path = os.path.join(
621 input_proto.output_dir, 'cpe_report.txt')
622 output_proto.artifacts.add().path = os.path.join(
623 input_proto.output_dir, 'cpe_warnings.txt')
624
625
626@faux.success(_ExportCpeReportResponse)
627@faux.empty_error
Alex Klein036833d2022-06-01 13:05:01 -0600628@validate.require('sysroot.path')
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600629@validate.exists('output_dir')
Alex Klein036833d2022-06-01 13:05:01 -0600630@validate.validation_complete
631def ExportCpeReport(input_proto: artifacts_pb2.BundleRequest,
632 output_proto: artifacts_pb2.BundleResponse,
633 _config: 'api_config.ApiConfig') -> None:
634 """Export a CPE report."""
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600635 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein036833d2022-06-01 13:05:01 -0600636 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600637 output_dir = input_proto.output_dir
638
Alex Klein036833d2022-06-01 13:05:01 -0600639 if not sysroot.Exists(chroot=chroot):
640 logging.warning('Sysroot does not exist: %s', sysroot.path)
641 return
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600642
643 cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
644
645 output_proto.artifacts.add().path = cpe_result.report
646 output_proto.artifacts.add().path = cpe_result.warnings
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900647
648
649def _BundleGceTarballResponse(input_proto, output_proto, _config):
650 """Add artifact tarball to a successful response."""
651 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
652 constants.TEST_IMAGE_GCE_TAR)
653
654
655@faux.success(_BundleGceTarballResponse)
656@faux.empty_error
657@validate.require('build_target.name', 'output_dir')
658@validate.exists('output_dir')
659@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000660def BundleGceTarball(
661 input_proto: artifacts_pb2.BundleRequest,
662 output_proto: artifacts_pb2.BundleResponse,
663 _config: 'api_config.ApiConfig'):
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900664 """Bundle the test image into a tarball suitable for importing into GCE.
665
666 Args:
Varun Somani04dccd72021-10-09 01:06:11 +0000667 input_proto: The input proto.
668 output_proto: The output proto.
669 _config: The API call config.
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900670 """
671 target = input_proto.build_target.name
672 output_dir = input_proto.output_dir
673 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
674 if image_dir is None:
675 return None
676
677 tarball = artifacts.BundleGceTarball(output_dir, image_dir)
678 output_proto.artifacts.add().path = tarball