blob: c658d16d9528c4c7d8f56489fcff0409c016cb68 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Evan Hernandezf388cbf2019-04-01 11:15:23 -06002# 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
Evan Hernandezf388cbf2019-04-01 11:15:23 -060020from chromite.lib import constants
21from chromite.lib import cros_build_lib
Alex Klein2275d692019-04-23 16:04:12 -060022from chromite.lib import sysroot_lib
23from chromite.service import artifacts
Greg Edelstondc941072021-08-11 12:32:30 -060024from chromite.service import test
Evan Hernandezf388cbf2019-04-01 11:15:23 -060025
Mike Frysinger1cc8f1f2022-04-28 22:40:40 -040026
Varun Somani04dccd72021-10-09 01:06:11 +000027if TYPE_CHECKING:
Alex Klein1699fab2022-09-08 08:46:06 -060028 from chromite.api import api_config
29
Evan Hernandezf388cbf2019-04-01 11:15:23 -060030
George Engelbrechtc9a8e812021-06-16 18:14:17 -060031class RegisteredGet(NamedTuple):
Alex Klein1699fab2022-09-08 08:46:06 -060032 """An registered function for calling Get on an artifact type."""
33
34 output_proto: artifacts_pb2.GetResponse
35 artifact_dict: Any
LaMont Jones0f5171b2021-01-29 12:28:56 -070036
37
George Engelbrechtc9a8e812021-06-16 18:14:17 -060038def ExampleGetResponse(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -060039 """Give an example GetResponse with a minimal coverage set."""
40 _output_proto = artifacts_pb2.GetResponse(
41 artifacts=common_pb2.UploadedArtifactsByService(
42 image=image_controller.ExampleGetResponse(),
43 sysroot=sysroot_controller.ExampleGetResponse(),
44 )
45 )
46 return controller.RETURN_CODE_SUCCESS
George Engelbrechtc9a8e812021-06-16 18:14:17 -060047
48
LaMont Jones0f5171b2021-01-29 12:28:56 -070049@faux.empty_error
George Engelbrechtc9a8e812021-06-16 18:14:17 -060050@faux.success(ExampleGetResponse)
Alex Klein1699fab2022-09-08 08:46:06 -060051@validate.exists("result_path.path.path")
LaMont Jones0f5171b2021-01-29 12:28:56 -070052@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +000053def Get(
54 input_proto: artifacts_pb2.GetRequest,
55 output_proto: artifacts_pb2.GetResponse,
Alex Klein1699fab2022-09-08 08:46:06 -060056 _config: "api_config.ApiConfig",
57):
58 """Get all artifacts.
LaMont Jones0f5171b2021-01-29 12:28:56 -070059
Alex Klein1699fab2022-09-08 08:46:06 -060060 Get all artifacts for the build.
LaMont Jones0f5171b2021-01-29 12:28:56 -070061
Alex Klein1699fab2022-09-08 08:46:06 -060062 Note: As the individual artifact_type bundlers are added here, they *must*
63 stop uploading it via the individual bundler function.
LaMont Jones0f5171b2021-01-29 12:28:56 -070064
Alex Klein1699fab2022-09-08 08:46:06 -060065 Args:
Alex Klein611dddd2022-10-11 17:02:01 -060066 input_proto: The input proto.
67 output_proto: The output proto.
68 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -060069 """
70 output_dir = input_proto.result_path.path.path
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000071
Alex Klein1699fab2022-09-08 08:46:06 -060072 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
73 # This endpoint does not currently support any artifacts that are built
74 # without a sysroot being present.
75 if not sysroot.path:
76 return controller.RETURN_CODE_SUCCESS
77
78 chroot = controller_util.ParseChroot(input_proto.chroot)
79 build_target = controller_util.ParseBuildTarget(
80 input_proto.sysroot.build_target
81 )
82
83 # A list of RegisteredGet tuples (input proto, output proto, get results).
84 get_res_list = [
85 RegisteredGet(
86 output_proto.artifacts.image,
87 image_controller.GetArtifacts(
88 input_proto.artifact_info.image,
89 chroot,
90 sysroot,
91 build_target,
92 output_dir,
93 ),
94 ),
95 RegisteredGet(
96 output_proto.artifacts.sysroot,
97 sysroot_controller.GetArtifacts(
98 input_proto.artifact_info.sysroot,
99 chroot,
100 sysroot,
101 build_target,
102 output_dir,
103 ),
104 ),
105 RegisteredGet(
106 output_proto.artifacts.test,
107 test_controller.GetArtifacts(
108 input_proto.artifact_info.test,
109 chroot,
110 sysroot,
111 build_target,
112 output_dir,
113 ),
114 ),
115 ]
116
117 for get_res in get_res_list:
118 for artifact_dict in get_res.artifact_dict:
119 get_res.output_proto.artifacts.add(
120 artifact_type=artifact_dict["type"],
121 paths=[
122 common_pb2.Path(
123 path=x, location=common_pb2.Path.Location.OUTSIDE
124 )
125 for x in artifact_dict["paths"]
126 ],
127 )
LaMont Jones8b88e9d2021-06-28 16:37:34 -0600128 return controller.RETURN_CODE_SUCCESS
129
LaMont Jones0f5171b2021-01-29 12:28:56 -0700130
LaMont Jones58362a42021-02-04 17:40:08 -0700131def _BuildSetupResponse(_input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600132 """Just return POINTLESS for now."""
133 # All of the artifact types we support claim that the build is POINTLESS.
134 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
LaMont Jones58362a42021-02-04 17:40:08 -0700135
136
137@faux.success(_BuildSetupResponse)
138@faux.empty_error
139@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000140def BuildSetup(
141 _input_proto: artifacts_pb2.GetRequest,
142 output_proto: artifacts_pb2.GetResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600143 _config: "api_config.ApiConfig",
144):
Varun Somani04dccd72021-10-09 01:06:11 +0000145
Alex Klein1699fab2022-09-08 08:46:06 -0600146 """Setup anything needed for building artifacts
LaMont Jones58362a42021-02-04 17:40:08 -0700147
Alex Klein1699fab2022-09-08 08:46:06 -0600148 If any artifact types require steps prior to building the package, they go
149 here. For example, see ToolchainService/PrepareForBuild.
LaMont Jones58362a42021-02-04 17:40:08 -0700150
Alex Klein1699fab2022-09-08 08:46:06 -0600151 Note: crbug/1034529 introduces this method as a noop. As the individual
152 artifact_type bundlers are added here, they *must* stop uploading it via the
153 individual bundler function.
LaMont Jones58362a42021-02-04 17:40:08 -0700154
Alex Klein1699fab2022-09-08 08:46:06 -0600155 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600156 _input_proto: The input proto.
157 output_proto: The output proto.
158 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600159 """
160 # If any artifact_type says "NEEDED", the return is NEEDED.
161 # Otherwise, if any artifact_type says "UNKNOWN", the return is UNKNOWN.
162 # Otherwise, the return is POINTLESS.
163 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
164 return controller.RETURN_CODE_SUCCESS
LaMont Jones58362a42021-02-04 17:40:08 -0700165
166
Varun Somani04dccd72021-10-09 01:06:11 +0000167def _GetImageDir(build_root: str, target: str) -> Optional[str]:
Alex Klein1699fab2022-09-08 08:46:06 -0600168 """Return path containing images for the given build target.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600169
Alex Klein1699fab2022-09-08 08:46:06 -0600170 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
Alex Kleine2612a02019-04-18 13:51:06 -0600171
Alex Klein1699fab2022-09-08 08:46:06 -0600172 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600173 build_root: Path to checkout where build occurs.
174 target: Name of the build target.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600175
Alex Klein1699fab2022-09-08 08:46:06 -0600176 Returns:
Alex Klein611dddd2022-10-11 17:02:01 -0600177 Path to the latest directory containing target images or None.
Alex Klein1699fab2022-09-08 08:46:06 -0600178 """
179 image_dir = os.path.join(build_root, "src/build/images", target, "latest")
180 if not os.path.exists(image_dir):
181 logging.warning(
182 "Expected to find image output for target %s at %s, but "
183 "path does not exist",
184 target,
185 image_dir,
186 )
187 return None
Alex Kleind2bf1462019-10-24 16:37:04 -0600188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 return image_dir
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600190
191
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700192def _BundleImageArchivesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600193 """Add artifact paths to a successful response."""
194 output_proto.artifacts.add().path = os.path.join(
195 input_proto.output_dir, "path0.tar.xz"
196 )
197 output_proto.artifacts.add().path = os.path.join(
198 input_proto.output_dir, "path1.tar.xz"
199 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700200
201
202@faux.success(_BundleImageArchivesResponse)
203@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600204@validate.require("build_target.name")
205@validate.exists("output_dir")
Alex Kleind91e95a2019-09-17 10:39:02 -0600206@validate.validation_complete
207def BundleImageArchives(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600208 """Create a .tar.xz archive for each image that has been created."""
209 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
210 output_dir = input_proto.output_dir
211 image_dir = _GetImageDir(constants.SOURCE_ROOT, build_target.name)
212 if image_dir is None:
213 return
Alex Kleind91e95a2019-09-17 10:39:02 -0600214
Alex Klein1699fab2022-09-08 08:46:06 -0600215 archives = artifacts.ArchiveImages(image_dir, output_dir)
Alex Kleind91e95a2019-09-17 10:39:02 -0600216
Alex Klein1699fab2022-09-08 08:46:06 -0600217 for archive in archives:
218 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Kleind91e95a2019-09-17 10:39:02 -0600219
220
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700221def _BundleImageZipResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600222 """Add artifact zip files to a successful response."""
223 output_proto.artifacts.add().path = os.path.join(
224 input_proto.output_dir, "image.zip"
225 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700226
227
228@faux.success(_BundleImageZipResponse)
229@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600230@validate.require("build_target.name", "output_dir")
231@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600232@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000233def BundleImageZip(
234 input_proto: artifacts_pb2.BundleRequest,
235 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600236 _config: "api_config.ApiConfig",
237):
238 """Bundle image.zip.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600239
Alex Klein1699fab2022-09-08 08:46:06 -0600240 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600241 input_proto: The input proto.
242 output_proto: The output proto.
243 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600244 """
245 target = input_proto.build_target.name
246 output_dir = input_proto.output_dir
247 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
248 if image_dir is None:
249 return None
Alex Klein231d2da2019-07-22 16:44:45 -0600250
Alex Klein1699fab2022-09-08 08:46:06 -0600251 archive = artifacts.BundleImageZip(output_dir, image_dir)
252 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600253
254
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700255def _BundleTestUpdatePayloadsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600256 """Add test payload files to a successful response."""
257 output_proto.artifacts.add().path = os.path.join(
258 input_proto.output_dir, "payload1.bin"
259 )
260 output_proto.artifacts.add().path = os.path.join(
261 input_proto.output_dir, "payload1.json"
262 )
263 output_proto.artifacts.add().path = os.path.join(
264 input_proto.output_dir, "payload1.log"
265 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700266
267
268@faux.success(_BundleTestUpdatePayloadsResponse)
269@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600270@validate.require("build_target.name", "output_dir")
271@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600272@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000273def BundleTestUpdatePayloads(
274 input_proto: artifacts_pb2.BundleRequest,
275 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600276 _config: "api_config.ApiConfig",
277):
278 """Generate minimal update payloads for the build target for testing.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600279
Alex Klein1699fab2022-09-08 08:46:06 -0600280 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600281 input_proto: The input proto.
282 output_proto: The output proto.
283 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600284 """
285 target = input_proto.build_target.name
286 output_dir = input_proto.output_dir
287 build_root = constants.SOURCE_ROOT
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600288
Alex Klein1699fab2022-09-08 08:46:06 -0600289 # Use the first available image to create the update payload.
290 img_dir = _GetImageDir(build_root, target)
291 if img_dir is None:
292 return None
Alex Kleind2bf1462019-10-24 16:37:04 -0600293
Alex Klein1699fab2022-09-08 08:46:06 -0600294 img_types = [
295 constants.IMAGE_TYPE_TEST,
296 constants.IMAGE_TYPE_DEV,
297 constants.IMAGE_TYPE_BASE,
298 ]
299 img_names = [constants.IMAGE_TYPE_TO_NAME[t] for t in img_types]
300 img_paths = [os.path.join(img_dir, x) for x in img_names]
301 valid_images = [x for x in img_paths if os.path.exists(x)]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600302
Alex Klein1699fab2022-09-08 08:46:06 -0600303 if not valid_images:
304 cros_build_lib.Die(
305 'Expected to find an image of type among %r for target "%s" '
306 "at path %s.",
307 img_types,
308 target,
309 img_dir,
310 )
311 image = valid_images[0]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600312
Alex Klein1699fab2022-09-08 08:46:06 -0600313 payloads = artifacts.BundleTestUpdatePayloads(image, output_dir)
314 for payload in payloads:
315 output_proto.artifacts.add().path = payload
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600316
317
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700318def _BundleAutotestFilesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600319 """Add test autotest files to a successful response."""
320 output_proto.artifacts.add().path = os.path.join(
321 input_proto.output_dir, "autotest-a.tar.gz"
322 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700323
324
325@faux.success(_BundleAutotestFilesResponse)
326@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600327@validate.require("sysroot.path")
328@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600329@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600330def BundleAutotestFiles(
331 input_proto: artifacts_pb2.BundleRequest,
332 output_proto: artifacts_pb2.BundleResponse,
333 _config: "api_config.ApiConfig",
334) -> None:
335 """Tar the autotest files for a build target."""
336 output_dir = input_proto.output_dir
337 chroot = controller_util.ParseChroot(input_proto.chroot)
338 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600339
Alex Klein1699fab2022-09-08 08:46:06 -0600340 if not sysroot.Exists(chroot=chroot):
341 logging.warning("Sysroot does not exist: %s", sysroot.path)
342 return
Alex Klein238d8862019-05-07 11:32:46 -0600343
Alex Klein1699fab2022-09-08 08:46:06 -0600344 try:
345 # Note that this returns the full path to *multiple* tarballs.
346 archives = artifacts.BundleAutotestFiles(chroot, sysroot, output_dir)
347 except artifacts.Error as e:
348 logging.warning(e)
349 return
Alex Klein238d8862019-05-07 11:32:46 -0600350
Alex Klein1699fab2022-09-08 08:46:06 -0600351 for archive in archives.values():
352 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600353
354
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700355def _BundleTastFilesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600356 """Add test tast files to a successful response."""
357 output_proto.artifacts.add().path = os.path.join(
358 input_proto.output_dir, "tast_bundles.tar.gz"
359 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700360
361
362@faux.success(_BundleTastFilesResponse)
363@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600364@validate.require("sysroot.path")
365@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600366@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600367def BundleTastFiles(
368 input_proto: artifacts_pb2.BundleRequest,
369 output_proto: artifacts_pb2.BundleResponse,
370 _config: "api_config.ApiConfig",
371) -> None:
372 """Tar the tast files for a build target."""
373 output_dir = input_proto.output_dir
374 chroot = controller_util.ParseChroot(input_proto.chroot)
375 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600376
Alex Klein1699fab2022-09-08 08:46:06 -0600377 if not sysroot.Exists(chroot=chroot):
378 logging.warning("Sysroot does not exist: %s", sysroot.path)
379 return
Alex Kleinb9d810b2019-07-01 12:38:02 -0600380
Alex Klein1699fab2022-09-08 08:46:06 -0600381 archive = artifacts.BundleTastFiles(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600382
Alex Klein1699fab2022-09-08 08:46:06 -0600383 if not archive:
384 logging.warning("Found no tast files for %s.", sysroot.path)
385 return
Alex Klein036833d2022-06-01 13:05:01 -0600386
Alex Klein1699fab2022-09-08 08:46:06 -0600387 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600388
389
Fergus Dall34d74e12020-09-29 15:52:32 +1000390def BundlePinnedGuestImages(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600391 # TODO(crbug/1034529): Remove this endpoint
392 pass
393
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700394
Fergus Dall34d74e12020-09-29 15:52:32 +1000395def FetchPinnedGuestImageUris(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600396 # TODO(crbug/1034529): Remove this endpoint
397 pass
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600398
399
Greg Edelstondc941072021-08-11 12:32:30 -0600400def _FetchMetadataResponse(_input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600401 """Populate the output_proto with sample data."""
402 for fp in ("/metadata/foo.txt", "/metadata/bar.jsonproto"):
403 output_proto.filepaths.add(
404 path=common_pb2.Path(path=fp, location=common_pb2.Path.OUTSIDE)
405 )
406 return controller.RETURN_CODE_SUCCESS
Greg Edelstondc941072021-08-11 12:32:30 -0600407
408
409@faux.success(_FetchMetadataResponse)
410@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600411@validate.exists("chroot.path")
412@validate.require("sysroot.path")
Greg Edelstondc941072021-08-11 12:32:30 -0600413@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000414def FetchMetadata(
415 input_proto: artifacts_pb2.FetchMetadataRequest,
416 output_proto: artifacts_pb2.FetchMetadataResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600417 _config: "api_config.ApiConfig",
418):
419 """FetchMetadata returns the paths to all build/test metadata files.
Greg Edelstondc941072021-08-11 12:32:30 -0600420
Alex Klein1699fab2022-09-08 08:46:06 -0600421 This implements ArtifactsService.FetchMetadata.
Greg Edelstondc941072021-08-11 12:32:30 -0600422
Alex Klein1699fab2022-09-08 08:46:06 -0600423 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600424 input_proto: The input proto.
425 output_proto: The output proto.
426 config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600427 """
428 chroot = controller_util.ParseChroot(input_proto.chroot)
429 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
430 for path in test.FindAllMetadataFiles(chroot, sysroot):
431 output_proto.filepaths.add(
432 path=common_pb2.Path(path=path, location=common_pb2.Path.OUTSIDE)
433 )
434 return controller.RETURN_CODE_SUCCESS
Greg Edelstondc941072021-08-11 12:32:30 -0600435
436
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700437def _BundleFirmwareResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600438 """Add test firmware image files to a successful response."""
439 output_proto.artifacts.add().path = os.path.join(
440 input_proto.output_dir, "firmware.tar.gz"
441 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700442
443
444@faux.success(_BundleFirmwareResponse)
445@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600446@validate.require("sysroot.path")
447@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600448@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600449def BundleFirmware(
450 input_proto: artifacts_pb2.BundleRequest,
451 output_proto: artifacts_pb2.BundleResponse,
452 _config: "api_config.ApiConfig",
453) -> None:
454 """Tar the firmware images for a build target."""
455 output_dir = input_proto.output_dir
456 chroot = controller_util.ParseChroot(input_proto.chroot)
457 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600458
Alex Klein1699fab2022-09-08 08:46:06 -0600459 if not chroot.exists():
460 logging.warning("Chroot does not exist: %s", chroot.path)
461 return
462 elif not sysroot.Exists(chroot=chroot):
463 logging.warning("Sysroot does not exist: %s", sysroot.path)
464 return
Alex Klein231d2da2019-07-22 16:44:45 -0600465
Alex Klein1699fab2022-09-08 08:46:06 -0600466 archive = artifacts.BuildFirmwareArchive(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600467
Alex Klein1699fab2022-09-08 08:46:06 -0600468 if not archive:
469 logging.warning(
470 "Could not create firmware archive. No firmware found for %s.",
471 sysroot.path,
472 )
473 return
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600474
Alex Klein1699fab2022-09-08 08:46:06 -0600475 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600476
477
Yicheng Liea1181f2020-09-22 11:51:10 -0700478def _BundleFpmcuUnittestsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600479 """Add fingerprint MCU unittest binaries to a successful response."""
480 output_proto.artifacts.add().path = os.path.join(
481 input_proto.output_dir, "fpmcu_unittests.tar.gz"
482 )
Yicheng Liea1181f2020-09-22 11:51:10 -0700483
484
485@faux.success(_BundleFpmcuUnittestsResponse)
486@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600487@validate.require("sysroot.path")
488@validate.exists("output_dir")
Yicheng Liea1181f2020-09-22 11:51:10 -0700489@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600490def BundleFpmcuUnittests(
491 input_proto: artifacts_pb2.BundleRequest,
492 output_proto: artifacts_pb2.BundleResponse,
493 _config: "api_config.ApiConfig",
494) -> None:
495 """Tar the fingerprint MCU unittest binaries for a build target.
Yicheng Liea1181f2020-09-22 11:51:10 -0700496
Alex Klein1699fab2022-09-08 08:46:06 -0600497 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600498 input_proto: The input proto.
499 output_proto: The output proto.
500 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600501 """
502 output_dir = input_proto.output_dir
503 chroot = controller_util.ParseChroot(input_proto.chroot)
504 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Yicheng Liea1181f2020-09-22 11:51:10 -0700505
Alex Klein1699fab2022-09-08 08:46:06 -0600506 if not chroot.exists():
507 logging.warning("Chroot does not exist: %s", chroot.path)
508 return
509 elif not sysroot.Exists(chroot=chroot):
510 logging.warning("Sysroot does not exist: %s", sysroot.path)
511 return
Yicheng Liea1181f2020-09-22 11:51:10 -0700512
Alex Klein1699fab2022-09-08 08:46:06 -0600513 archive = artifacts.BundleFpmcuUnittests(chroot, sysroot, output_dir)
Yicheng Liea1181f2020-09-22 11:51:10 -0700514
Alex Klein1699fab2022-09-08 08:46:06 -0600515 if not archive:
516 logging.warning("No fpmcu unittests found for %s.", sysroot.path)
517 return
Yicheng Liea1181f2020-09-22 11:51:10 -0700518
Alex Klein1699fab2022-09-08 08:46:06 -0600519 output_proto.artifacts.add().path = archive
Yicheng Liea1181f2020-09-22 11:51:10 -0700520
521
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700522def _BundleEbuildLogsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600523 """Add test log files to a successful response."""
524 output_proto.artifacts.add().path = os.path.join(
525 input_proto.output_dir, "ebuild-logs.tar.gz"
526 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700527
528
529@faux.success(_BundleEbuildLogsResponse)
530@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600531@validate.require("sysroot.path")
532@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600533@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600534def BundleEbuildLogs(
535 input_proto: artifacts_pb2.BundleRequest,
536 output_proto: artifacts_pb2.BundleResponse,
537 _config: "api_config.ApiConfig",
538) -> None:
539 """Tar the ebuild logs for a build target."""
540 output_dir = input_proto.output_dir
541 chroot = controller_util.ParseChroot(input_proto.chroot)
542 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Evan Hernandeza478d802019-04-08 15:08:24 -0600543
Alex Klein1699fab2022-09-08 08:46:06 -0600544 if not sysroot.Exists(chroot=chroot):
545 logging.warning("Sysroot does not exist: %s", sysroot.path)
546 return
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600547
Alex Klein1699fab2022-09-08 08:46:06 -0600548 archive = artifacts.BundleEBuildLogsTarball(chroot, sysroot, output_dir)
Alex Klein036833d2022-06-01 13:05:01 -0600549
Alex Klein1699fab2022-09-08 08:46:06 -0600550 if not archive:
551 logging.warning(
552 "Could not create ebuild logs archive. No logs found for %s.",
553 sysroot.path,
554 )
555 return
Alex Klein036833d2022-06-01 13:05:01 -0600556
Alex Klein1699fab2022-09-08 08:46:06 -0600557 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600558
559
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700560def _BundleChromeOSConfigResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600561 """Add test config files to a successful response."""
562 output_proto.artifacts.add().path = os.path.join(
563 input_proto.output_dir, "config.yaml"
564 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700565
566
567@faux.success(_BundleChromeOSConfigResponse)
568@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600569@validate.require("sysroot.path")
570@validate.exists("output_dir")
Andrew Lamb811aead2019-08-12 10:25:05 -0600571@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000572def BundleChromeOSConfig(
573 input_proto: artifacts_pb2.BundleRequest,
574 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600575 _config: "api_config.ApiConfig",
576) -> None:
577 """Output the ChromeOS Config payload for a build target."""
578 output_dir = input_proto.output_dir
579 chroot = controller_util.ParseChroot(input_proto.chroot)
580 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Andrew Lamb811aead2019-08-12 10:25:05 -0600581
Alex Klein1699fab2022-09-08 08:46:06 -0600582 chromeos_config = artifacts.BundleChromeOSConfig(
583 chroot, sysroot, output_dir
584 )
Alex Klein2d8333c2022-06-01 13:29:01 -0600585
Alex Klein1699fab2022-09-08 08:46:06 -0600586 if not chromeos_config:
587 logging.warning(
588 "Could not create ChromeOS Config for %s.", sysroot.path
589 )
590 return
Alex Klein383a7a32021-12-07 16:01:19 -0700591
Alex Klein1699fab2022-09-08 08:46:06 -0600592 output_proto.artifacts.add().path = os.path.join(
593 output_dir, chromeos_config
594 )
Andrew Lamb811aead2019-08-12 10:25:05 -0600595
596
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700597def _BundleSimpleChromeArtifactsResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600598 """Add test simple chrome files to a successful response."""
599 output_proto.artifacts.add().path = os.path.join(
600 input_proto.output_dir, "simple_chrome.txt"
601 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700602
603
604@faux.success(_BundleSimpleChromeArtifactsResponse)
605@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600606@validate.require("output_dir", "sysroot.build_target.name", "sysroot.path")
607@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600608@validate.validation_complete
609def BundleSimpleChromeArtifacts(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600610 """Create the simple chrome artifacts."""
611 sysroot_path = input_proto.sysroot.path
612 output_dir = input_proto.output_dir
Alex Klein2275d692019-04-23 16:04:12 -0600613
Alex Klein1699fab2022-09-08 08:46:06 -0600614 # Build out the argument instances.
615 build_target = controller_util.ParseBuildTarget(
616 input_proto.sysroot.build_target
617 )
618 chroot = controller_util.ParseChroot(input_proto.chroot)
619 # Sysroot.path needs to be the fully qualified path, including the chroot.
620 full_sysroot_path = os.path.join(chroot.path, sysroot_path.lstrip(os.sep))
621 sysroot = sysroot_lib.Sysroot(full_sysroot_path)
Alex Klein2275d692019-04-23 16:04:12 -0600622
Alex Klein1699fab2022-09-08 08:46:06 -0600623 # Check that the sysroot exists before we go on.
624 if not sysroot.Exists():
625 cros_build_lib.Die("The sysroot does not exist.")
Alex Klein2275d692019-04-23 16:04:12 -0600626
Alex Klein1699fab2022-09-08 08:46:06 -0600627 try:
628 results = artifacts.BundleSimpleChromeArtifacts(
629 chroot, sysroot, build_target, output_dir
630 )
631 except artifacts.Error as e:
632 cros_build_lib.Die(
633 "Error %s raised in BundleSimpleChromeArtifacts: %s", type(e), e
634 )
Alex Klein2275d692019-04-23 16:04:12 -0600635
Alex Klein1699fab2022-09-08 08:46:06 -0600636 for file_name in results:
637 output_proto.artifacts.add().path = file_name
Alex Klein2275d692019-04-23 16:04:12 -0600638
639
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700640def _BundleVmFilesResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600641 """Add test vm files to a successful response."""
642 output_proto.artifacts.add().path = os.path.join(
643 input_proto.output_dir, "f1.tar"
644 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700645
646
647@faux.success(_BundleVmFilesResponse)
648@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600649@validate.require("chroot.path", "test_results_dir", "output_dir")
650@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600651@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000652def BundleVmFiles(
653 input_proto: artifacts_pb2.BundleVmFilesRequest,
654 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600655 _config: "api_config.ApiConfig",
656):
657 """Tar VM disk and memory files.
Alex Klein6504eca2019-04-18 15:37:56 -0600658
Alex Klein1699fab2022-09-08 08:46:06 -0600659 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600660 input_proto: The input proto.
661 output_proto: The output proto.
662 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600663 """
664 chroot = controller_util.ParseChroot(input_proto.chroot)
665 test_results_dir = input_proto.test_results_dir
666 output_dir = input_proto.output_dir
Alex Klein6504eca2019-04-18 15:37:56 -0600667
Alex Klein1699fab2022-09-08 08:46:06 -0600668 archives = artifacts.BundleVmFiles(chroot, test_results_dir, output_dir)
669 for archive in archives:
670 output_proto.artifacts.add().path = archive
671
Tiancong Wangc4805b72019-06-11 12:12:03 -0700672
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700673def _ExportCpeReportResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600674 """Add test cpe results to a successful response."""
675 output_proto.artifacts.add().path = os.path.join(
676 input_proto.output_dir, "cpe_report.txt"
677 )
678 output_proto.artifacts.add().path = os.path.join(
679 input_proto.output_dir, "cpe_warnings.txt"
680 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700681
682
683@faux.success(_ExportCpeReportResponse)
684@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600685@validate.require("sysroot.path")
686@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600687@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600688def ExportCpeReport(
689 input_proto: artifacts_pb2.BundleRequest,
690 output_proto: artifacts_pb2.BundleResponse,
691 _config: "api_config.ApiConfig",
692) -> None:
693 """Export a CPE report."""
694 chroot = controller_util.ParseChroot(input_proto.chroot)
695 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
696 output_dir = input_proto.output_dir
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600697
Alex Klein1699fab2022-09-08 08:46:06 -0600698 if not sysroot.Exists(chroot=chroot):
699 logging.warning("Sysroot does not exist: %s", sysroot.path)
700 return
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600701
Alex Klein1699fab2022-09-08 08:46:06 -0600702 cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600703
Alex Klein1699fab2022-09-08 08:46:06 -0600704 output_proto.artifacts.add().path = cpe_result.report
705 output_proto.artifacts.add().path = cpe_result.warnings
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900706
707
708def _BundleGceTarballResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600709 """Add artifact tarball to a successful response."""
710 output_proto.artifacts.add().path = os.path.join(
711 input_proto.output_dir, constants.TEST_IMAGE_GCE_TAR
712 )
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900713
714
715@faux.success(_BundleGceTarballResponse)
716@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600717@validate.require("build_target.name", "output_dir")
718@validate.exists("output_dir")
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900719@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000720def BundleGceTarball(
721 input_proto: artifacts_pb2.BundleRequest,
722 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600723 _config: "api_config.ApiConfig",
724):
725 """Bundle the test image into a tarball suitable for importing into GCE.
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900726
Alex Klein1699fab2022-09-08 08:46:06 -0600727 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600728 input_proto: The input proto.
729 output_proto: The output proto.
730 _config: The API call config.
Alex Klein1699fab2022-09-08 08:46:06 -0600731 """
732 target = input_proto.build_target.name
733 output_dir = input_proto.output_dir
734 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
735 if image_dir is None:
736 return None
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900737
Alex Klein1699fab2022-09-08 08:46:06 -0600738 tarball = artifacts.BundleGceTarball(output_dir, image_dir)
739 output_proto.artifacts.add().path = tarball