blob: 70ee6507f9b24b105a16420858f35bb9bf2594ec [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 Kleinb6847e22022-11-07 10:44:48 -070032 """A registered function for calling Get on an artifact type."""
Alex Klein1699fab2022-09-08 08:46:06 -060033
34 output_proto: artifacts_pb2.GetResponse
35 artifact_dict: Any
LaMont Jones0f5171b2021-01-29 12:28:56 -070036
37
Alex Kleinb6847e22022-11-07 10:44:48 -070038def ExampleGetResponse(_input_proto, _output_proto, _config) -> Optional[int]:
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",
Alex Kleinb6847e22022-11-07 10:44:48 -070057) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -060058 """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.
Alex Klein1699fab2022-09-08 08:46:06 -060064 """
65 output_dir = input_proto.result_path.path.path
Jaques Clapauchf616bcd2021-04-09 20:14:40 +000066
Alex Klein1699fab2022-09-08 08:46:06 -060067 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
68 # This endpoint does not currently support any artifacts that are built
69 # without a sysroot being present.
70 if not sysroot.path:
71 return controller.RETURN_CODE_SUCCESS
72
73 chroot = controller_util.ParseChroot(input_proto.chroot)
74 build_target = controller_util.ParseBuildTarget(
75 input_proto.sysroot.build_target
76 )
77
78 # A list of RegisteredGet tuples (input proto, output proto, get results).
79 get_res_list = [
80 RegisteredGet(
81 output_proto.artifacts.image,
82 image_controller.GetArtifacts(
83 input_proto.artifact_info.image,
84 chroot,
85 sysroot,
86 build_target,
87 output_dir,
88 ),
89 ),
90 RegisteredGet(
91 output_proto.artifacts.sysroot,
92 sysroot_controller.GetArtifacts(
93 input_proto.artifact_info.sysroot,
94 chroot,
95 sysroot,
96 build_target,
97 output_dir,
98 ),
99 ),
100 RegisteredGet(
101 output_proto.artifacts.test,
102 test_controller.GetArtifacts(
103 input_proto.artifact_info.test,
104 chroot,
105 sysroot,
106 build_target,
107 output_dir,
108 ),
109 ),
110 ]
111
112 for get_res in get_res_list:
113 for artifact_dict in get_res.artifact_dict:
Jack Neus26b94672022-10-27 17:33:21 +0000114 kwargs = {}
115 # TODO(b/255838545): Remove the kwargs funkness when these fields
116 # have been added for all services.
117 if "failed" in artifact_dict:
118 kwargs["failed"] = artifact_dict.get("failed", False)
119 kwargs["failure_reason"] = artifact_dict.get("failure_reason")
Alex Klein1699fab2022-09-08 08:46:06 -0600120 get_res.output_proto.artifacts.add(
121 artifact_type=artifact_dict["type"],
122 paths=[
123 common_pb2.Path(
124 path=x, location=common_pb2.Path.Location.OUTSIDE
125 )
Jack Neus26b94672022-10-27 17:33:21 +0000126 for x in artifact_dict.get("paths", [])
Alex Klein1699fab2022-09-08 08:46:06 -0600127 ],
Jack Neus26b94672022-10-27 17:33:21 +0000128 **kwargs,
Alex Klein1699fab2022-09-08 08:46:06 -0600129 )
LaMont Jones8b88e9d2021-06-28 16:37:34 -0600130 return controller.RETURN_CODE_SUCCESS
131
LaMont Jones0f5171b2021-01-29 12:28:56 -0700132
Alex Kleinb6847e22022-11-07 10:44:48 -0700133def _BuildSetupResponse(_input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600134 """Just return POINTLESS for now."""
Alex Kleinb6847e22022-11-07 10:44:48 -0700135 # All the artifact types we support claim that the build is POINTLESS.
Alex Klein1699fab2022-09-08 08:46:06 -0600136 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
LaMont Jones58362a42021-02-04 17:40:08 -0700137
138
139@faux.success(_BuildSetupResponse)
140@faux.empty_error
141@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000142def BuildSetup(
143 _input_proto: artifacts_pb2.GetRequest,
144 output_proto: artifacts_pb2.GetResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600145 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700146) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600147 """Setup anything needed for building artifacts
LaMont Jones58362a42021-02-04 17:40:08 -0700148
Alex Klein1699fab2022-09-08 08:46:06 -0600149 If any artifact types require steps prior to building the package, they go
150 here. For example, see ToolchainService/PrepareForBuild.
LaMont Jones58362a42021-02-04 17:40:08 -0700151
Alex Klein1699fab2022-09-08 08:46:06 -0600152 Note: crbug/1034529 introduces this method as a noop. As the individual
153 artifact_type bundlers are added here, they *must* stop uploading it via the
154 individual bundler function.
Alex Klein1699fab2022-09-08 08:46:06 -0600155 """
156 # If any artifact_type says "NEEDED", the return is NEEDED.
157 # Otherwise, if any artifact_type says "UNKNOWN", the return is UNKNOWN.
158 # Otherwise, the return is POINTLESS.
159 output_proto.build_relevance = artifacts_pb2.BuildSetupResponse.POINTLESS
160 return controller.RETURN_CODE_SUCCESS
LaMont Jones58362a42021-02-04 17:40:08 -0700161
162
Varun Somani04dccd72021-10-09 01:06:11 +0000163def _GetImageDir(build_root: str, target: str) -> Optional[str]:
Alex Klein1699fab2022-09-08 08:46:06 -0600164 """Return path containing images for the given build target.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600165
Alex Klein1699fab2022-09-08 08:46:06 -0600166 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
Alex Kleine2612a02019-04-18 13:51:06 -0600167
Alex Klein1699fab2022-09-08 08:46:06 -0600168 Args:
Alex Klein611dddd2022-10-11 17:02:01 -0600169 build_root: Path to checkout where build occurs.
170 target: Name of the build target.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600171
Alex Klein1699fab2022-09-08 08:46:06 -0600172 Returns:
Alex Klein611dddd2022-10-11 17:02:01 -0600173 Path to the latest directory containing target images or None.
Alex Klein1699fab2022-09-08 08:46:06 -0600174 """
175 image_dir = os.path.join(build_root, "src/build/images", target, "latest")
176 if not os.path.exists(image_dir):
177 logging.warning(
178 "Expected to find image output for target %s at %s, but "
179 "path does not exist",
180 target,
181 image_dir,
182 )
183 return None
Alex Kleind2bf1462019-10-24 16:37:04 -0600184
Alex Klein1699fab2022-09-08 08:46:06 -0600185 return image_dir
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600186
187
Alex Kleinb6847e22022-11-07 10:44:48 -0700188def _BundleImageArchivesResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600189 """Add artifact paths to a successful response."""
190 output_proto.artifacts.add().path = os.path.join(
191 input_proto.output_dir, "path0.tar.xz"
192 )
193 output_proto.artifacts.add().path = os.path.join(
194 input_proto.output_dir, "path1.tar.xz"
195 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700196
197
198@faux.success(_BundleImageArchivesResponse)
199@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600200@validate.require("build_target.name")
201@validate.exists("output_dir")
Alex Kleind91e95a2019-09-17 10:39:02 -0600202@validate.validation_complete
Alex Kleinb6847e22022-11-07 10:44:48 -0700203def BundleImageArchives(
204 input_proto: artifacts_pb2.BundleRequest,
205 output_proto: artifacts_pb2.BundleResponse,
206 _config: "api_config.ApiConfig",
207) -> Optional[int]:
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
Alex Kleinb6847e22022-11-07 10:44:48 -0700221def _BundleImageZipResponse(input_proto, output_proto, _config) -> None:
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",
Alex Kleinb6847e22022-11-07 10:44:48 -0700237) -> Optional[int]:
238 """Bundle image.zip."""
Alex Klein1699fab2022-09-08 08:46:06 -0600239 target = input_proto.build_target.name
240 output_dir = input_proto.output_dir
241 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
242 if image_dir is None:
Alex Kleinb6847e22022-11-07 10:44:48 -0700243 logging.warning("Image build directory not found.")
Alex Klein1699fab2022-09-08 08:46:06 -0600244 return None
Alex Klein231d2da2019-07-22 16:44:45 -0600245
Alex Klein1699fab2022-09-08 08:46:06 -0600246 archive = artifacts.BundleImageZip(output_dir, image_dir)
247 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600248
249
Alex Kleinb6847e22022-11-07 10:44:48 -0700250def _BundleTestUpdatePayloadsResponse(
251 input_proto, output_proto, _config
252) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600253 """Add test payload files to a successful response."""
254 output_proto.artifacts.add().path = os.path.join(
255 input_proto.output_dir, "payload1.bin"
256 )
257 output_proto.artifacts.add().path = os.path.join(
258 input_proto.output_dir, "payload1.json"
259 )
260 output_proto.artifacts.add().path = os.path.join(
261 input_proto.output_dir, "payload1.log"
262 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700263
264
265@faux.success(_BundleTestUpdatePayloadsResponse)
266@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600267@validate.require("build_target.name", "output_dir")
268@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600269@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000270def BundleTestUpdatePayloads(
271 input_proto: artifacts_pb2.BundleRequest,
272 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600273 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700274) -> Optional[int]:
275 """Generate minimal update payloads for the build target for testing."""
Alex Klein1699fab2022-09-08 08:46:06 -0600276 target = input_proto.build_target.name
277 output_dir = input_proto.output_dir
Brian Norrisdd2e7e62023-06-16 14:07:32 -0700278 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein1699fab2022-09-08 08:46:06 -0600279 build_root = constants.SOURCE_ROOT
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600280
Alex Klein1699fab2022-09-08 08:46:06 -0600281 # Use the first available image to create the update payload.
282 img_dir = _GetImageDir(build_root, target)
283 if img_dir is None:
284 return None
Alex Kleind2bf1462019-10-24 16:37:04 -0600285
Alex Klein1699fab2022-09-08 08:46:06 -0600286 img_types = [
287 constants.IMAGE_TYPE_TEST,
288 constants.IMAGE_TYPE_DEV,
289 constants.IMAGE_TYPE_BASE,
290 ]
291 img_names = [constants.IMAGE_TYPE_TO_NAME[t] for t in img_types]
292 img_paths = [os.path.join(img_dir, x) for x in img_names]
293 valid_images = [x for x in img_paths if os.path.exists(x)]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600294
Alex Klein1699fab2022-09-08 08:46:06 -0600295 if not valid_images:
296 cros_build_lib.Die(
297 'Expected to find an image of type among %r for target "%s" '
298 "at path %s.",
299 img_types,
300 target,
301 img_dir,
302 )
303 image = valid_images[0]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600304
Brian Norrisdd2e7e62023-06-16 14:07:32 -0700305 payloads = artifacts.BundleTestUpdatePayloads(chroot, image, output_dir)
Alex Klein1699fab2022-09-08 08:46:06 -0600306 for payload in payloads:
307 output_proto.artifacts.add().path = payload
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600308
309
Alex Kleinb6847e22022-11-07 10:44:48 -0700310def _BundleAutotestFilesResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600311 """Add test autotest files to a successful response."""
312 output_proto.artifacts.add().path = os.path.join(
313 input_proto.output_dir, "autotest-a.tar.gz"
314 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700315
316
317@faux.success(_BundleAutotestFilesResponse)
318@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600319@validate.require("sysroot.path")
320@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600321@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600322def BundleAutotestFiles(
323 input_proto: artifacts_pb2.BundleRequest,
324 output_proto: artifacts_pb2.BundleResponse,
325 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700326) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600327 """Tar the autotest files for a build target."""
328 output_dir = input_proto.output_dir
329 chroot = controller_util.ParseChroot(input_proto.chroot)
330 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600331
Alex Klein1699fab2022-09-08 08:46:06 -0600332 if not sysroot.Exists(chroot=chroot):
333 logging.warning("Sysroot does not exist: %s", sysroot.path)
334 return
Alex Klein238d8862019-05-07 11:32:46 -0600335
Alex Klein1699fab2022-09-08 08:46:06 -0600336 try:
337 # Note that this returns the full path to *multiple* tarballs.
338 archives = artifacts.BundleAutotestFiles(chroot, sysroot, output_dir)
339 except artifacts.Error as e:
340 logging.warning(e)
341 return
Alex Klein238d8862019-05-07 11:32:46 -0600342
Alex Klein1699fab2022-09-08 08:46:06 -0600343 for archive in archives.values():
344 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600345
346
Alex Kleinb6847e22022-11-07 10:44:48 -0700347def _BundleTastFilesResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600348 """Add test tast files to a successful response."""
349 output_proto.artifacts.add().path = os.path.join(
350 input_proto.output_dir, "tast_bundles.tar.gz"
351 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700352
353
354@faux.success(_BundleTastFilesResponse)
355@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600356@validate.require("sysroot.path")
357@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600358@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600359def BundleTastFiles(
360 input_proto: artifacts_pb2.BundleRequest,
361 output_proto: artifacts_pb2.BundleResponse,
362 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700363) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600364 """Tar the tast files for a build target."""
365 output_dir = input_proto.output_dir
366 chroot = controller_util.ParseChroot(input_proto.chroot)
367 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Kleinb9d810b2019-07-01 12:38:02 -0600368
Alex Klein1699fab2022-09-08 08:46:06 -0600369 if not sysroot.Exists(chroot=chroot):
370 logging.warning("Sysroot does not exist: %s", sysroot.path)
371 return
Alex Kleinb9d810b2019-07-01 12:38:02 -0600372
Alex Klein1699fab2022-09-08 08:46:06 -0600373 archive = artifacts.BundleTastFiles(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600374
Alex Klein1699fab2022-09-08 08:46:06 -0600375 if not archive:
376 logging.warning("Found no tast files for %s.", sysroot.path)
377 return
Alex Klein036833d2022-06-01 13:05:01 -0600378
Alex Klein1699fab2022-09-08 08:46:06 -0600379 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600380
381
Fergus Dall34d74e12020-09-29 15:52:32 +1000382def BundlePinnedGuestImages(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600383 # TODO(crbug/1034529): Remove this endpoint
384 pass
385
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700386
Fergus Dall34d74e12020-09-29 15:52:32 +1000387def FetchPinnedGuestImageUris(_input_proto, _output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600388 # TODO(crbug/1034529): Remove this endpoint
389 pass
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600390
391
Alex Kleinb6847e22022-11-07 10:44:48 -0700392def _FetchMetadataResponse(
393 _input_proto, output_proto, _config
394) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600395 """Populate the output_proto with sample data."""
396 for fp in ("/metadata/foo.txt", "/metadata/bar.jsonproto"):
397 output_proto.filepaths.add(
398 path=common_pb2.Path(path=fp, location=common_pb2.Path.OUTSIDE)
399 )
400 return controller.RETURN_CODE_SUCCESS
Greg Edelstondc941072021-08-11 12:32:30 -0600401
402
403@faux.success(_FetchMetadataResponse)
404@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600405@validate.exists("chroot.path")
406@validate.require("sysroot.path")
Greg Edelstondc941072021-08-11 12:32:30 -0600407@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000408def FetchMetadata(
409 input_proto: artifacts_pb2.FetchMetadataRequest,
410 output_proto: artifacts_pb2.FetchMetadataResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600411 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700412) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600413 """FetchMetadata returns the paths to all build/test metadata files.
Greg Edelstondc941072021-08-11 12:32:30 -0600414
Alex Klein1699fab2022-09-08 08:46:06 -0600415 This implements ArtifactsService.FetchMetadata.
Alex Klein1699fab2022-09-08 08:46:06 -0600416 """
417 chroot = controller_util.ParseChroot(input_proto.chroot)
418 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
419 for path in test.FindAllMetadataFiles(chroot, sysroot):
420 output_proto.filepaths.add(
421 path=common_pb2.Path(path=path, location=common_pb2.Path.OUTSIDE)
422 )
423 return controller.RETURN_CODE_SUCCESS
Greg Edelstondc941072021-08-11 12:32:30 -0600424
425
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700426def _BundleFirmwareResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600427 """Add test firmware image files to a successful response."""
428 output_proto.artifacts.add().path = os.path.join(
429 input_proto.output_dir, "firmware.tar.gz"
430 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700431
432
433@faux.success(_BundleFirmwareResponse)
434@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600435@validate.require("sysroot.path")
436@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600437@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600438def BundleFirmware(
439 input_proto: artifacts_pb2.BundleRequest,
440 output_proto: artifacts_pb2.BundleResponse,
441 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700442) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600443 """Tar the firmware images for a build target."""
444 output_dir = input_proto.output_dir
445 chroot = controller_util.ParseChroot(input_proto.chroot)
446 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Alex Klein231d2da2019-07-22 16:44:45 -0600447
Alex Klein1699fab2022-09-08 08:46:06 -0600448 if not chroot.exists():
449 logging.warning("Chroot does not exist: %s", chroot.path)
450 return
451 elif not sysroot.Exists(chroot=chroot):
452 logging.warning("Sysroot does not exist: %s", sysroot.path)
453 return
Alex Klein231d2da2019-07-22 16:44:45 -0600454
Alex Klein1699fab2022-09-08 08:46:06 -0600455 archive = artifacts.BuildFirmwareArchive(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600456
Alex Klein1699fab2022-09-08 08:46:06 -0600457 if not archive:
458 logging.warning(
459 "Could not create firmware archive. No firmware found for %s.",
460 sysroot.path,
461 )
462 return
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600463
Alex Klein1699fab2022-09-08 08:46:06 -0600464 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600465
466
Alex Kleinb6847e22022-11-07 10:44:48 -0700467def _BundleFpmcuUnittestsResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600468 """Add fingerprint MCU unittest binaries to a successful response."""
469 output_proto.artifacts.add().path = os.path.join(
470 input_proto.output_dir, "fpmcu_unittests.tar.gz"
471 )
Yicheng Liea1181f2020-09-22 11:51:10 -0700472
473
474@faux.success(_BundleFpmcuUnittestsResponse)
475@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600476@validate.require("sysroot.path")
477@validate.exists("output_dir")
Yicheng Liea1181f2020-09-22 11:51:10 -0700478@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600479def BundleFpmcuUnittests(
480 input_proto: artifacts_pb2.BundleRequest,
481 output_proto: artifacts_pb2.BundleResponse,
482 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700483) -> Optional[int]:
484 """Tar the fingerprint MCU unittest binaries for a build target."""
Alex Klein1699fab2022-09-08 08:46:06 -0600485 output_dir = input_proto.output_dir
486 chroot = controller_util.ParseChroot(input_proto.chroot)
487 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Yicheng Liea1181f2020-09-22 11:51:10 -0700488
Alex Klein1699fab2022-09-08 08:46:06 -0600489 if not chroot.exists():
490 logging.warning("Chroot does not exist: %s", chroot.path)
491 return
492 elif not sysroot.Exists(chroot=chroot):
493 logging.warning("Sysroot does not exist: %s", sysroot.path)
494 return
Yicheng Liea1181f2020-09-22 11:51:10 -0700495
Alex Klein1699fab2022-09-08 08:46:06 -0600496 archive = artifacts.BundleFpmcuUnittests(chroot, sysroot, output_dir)
Yicheng Liea1181f2020-09-22 11:51:10 -0700497
Alex Klein1699fab2022-09-08 08:46:06 -0600498 if not archive:
499 logging.warning("No fpmcu unittests found for %s.", sysroot.path)
500 return
Yicheng Liea1181f2020-09-22 11:51:10 -0700501
Alex Klein1699fab2022-09-08 08:46:06 -0600502 output_proto.artifacts.add().path = archive
Yicheng Liea1181f2020-09-22 11:51:10 -0700503
504
Alex Kleinb6847e22022-11-07 10:44:48 -0700505def _BundleEbuildLogsResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600506 """Add test log files to a successful response."""
507 output_proto.artifacts.add().path = os.path.join(
508 input_proto.output_dir, "ebuild-logs.tar.gz"
509 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700510
511
512@faux.success(_BundleEbuildLogsResponse)
513@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600514@validate.require("sysroot.path")
515@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600516@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600517def BundleEbuildLogs(
518 input_proto: artifacts_pb2.BundleRequest,
519 output_proto: artifacts_pb2.BundleResponse,
520 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700521) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600522 """Tar the ebuild logs for a build target."""
523 output_dir = input_proto.output_dir
524 chroot = controller_util.ParseChroot(input_proto.chroot)
525 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Evan Hernandeza478d802019-04-08 15:08:24 -0600526
Alex Klein1699fab2022-09-08 08:46:06 -0600527 if not sysroot.Exists(chroot=chroot):
528 logging.warning("Sysroot does not exist: %s", sysroot.path)
529 return
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600530
Alex Klein1699fab2022-09-08 08:46:06 -0600531 archive = artifacts.BundleEBuildLogsTarball(chroot, sysroot, output_dir)
Alex Klein036833d2022-06-01 13:05:01 -0600532
Alex Klein1699fab2022-09-08 08:46:06 -0600533 if not archive:
534 logging.warning(
535 "Could not create ebuild logs archive. No logs found for %s.",
536 sysroot.path,
537 )
538 return
Alex Klein036833d2022-06-01 13:05:01 -0600539
Alex Klein1699fab2022-09-08 08:46:06 -0600540 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600541
542
Alex Kleinb6847e22022-11-07 10:44:48 -0700543def _BundleChromeOSConfigResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600544 """Add test config files to a successful response."""
545 output_proto.artifacts.add().path = os.path.join(
546 input_proto.output_dir, "config.yaml"
547 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700548
549
550@faux.success(_BundleChromeOSConfigResponse)
551@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600552@validate.require("sysroot.path")
553@validate.exists("output_dir")
Andrew Lamb811aead2019-08-12 10:25:05 -0600554@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000555def BundleChromeOSConfig(
556 input_proto: artifacts_pb2.BundleRequest,
557 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600558 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700559) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600560 """Output the ChromeOS Config payload for a build target."""
561 output_dir = input_proto.output_dir
562 chroot = controller_util.ParseChroot(input_proto.chroot)
563 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
Andrew Lamb811aead2019-08-12 10:25:05 -0600564
Alex Klein1699fab2022-09-08 08:46:06 -0600565 chromeos_config = artifacts.BundleChromeOSConfig(
566 chroot, sysroot, output_dir
567 )
Alex Klein2d8333c2022-06-01 13:29:01 -0600568
Alex Klein1699fab2022-09-08 08:46:06 -0600569 if not chromeos_config:
570 logging.warning(
571 "Could not create ChromeOS Config for %s.", sysroot.path
572 )
573 return
Alex Klein383a7a32021-12-07 16:01:19 -0700574
Alex Klein1699fab2022-09-08 08:46:06 -0600575 output_proto.artifacts.add().path = os.path.join(
576 output_dir, chromeos_config
577 )
Andrew Lamb811aead2019-08-12 10:25:05 -0600578
579
Alex Kleinb6847e22022-11-07 10:44:48 -0700580def _BundleSimpleChromeArtifactsResponse(
581 input_proto, output_proto, _config
582) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600583 """Add test simple chrome files to a successful response."""
584 output_proto.artifacts.add().path = os.path.join(
585 input_proto.output_dir, "simple_chrome.txt"
586 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700587
588
589@faux.success(_BundleSimpleChromeArtifactsResponse)
590@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600591@validate.require("output_dir", "sysroot.build_target.name", "sysroot.path")
592@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600593@validate.validation_complete
Alex Kleinb6847e22022-11-07 10:44:48 -0700594def BundleSimpleChromeArtifacts(
595 input_proto, output_proto, _config
596) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600597 """Create the simple chrome artifacts."""
598 sysroot_path = input_proto.sysroot.path
599 output_dir = input_proto.output_dir
Alex Klein2275d692019-04-23 16:04:12 -0600600
Alex Klein1699fab2022-09-08 08:46:06 -0600601 # Build out the argument instances.
602 build_target = controller_util.ParseBuildTarget(
603 input_proto.sysroot.build_target
604 )
605 chroot = controller_util.ParseChroot(input_proto.chroot)
606 # Sysroot.path needs to be the fully qualified path, including the chroot.
607 full_sysroot_path = os.path.join(chroot.path, sysroot_path.lstrip(os.sep))
608 sysroot = sysroot_lib.Sysroot(full_sysroot_path)
Alex Klein2275d692019-04-23 16:04:12 -0600609
Alex Klein1699fab2022-09-08 08:46:06 -0600610 # Check that the sysroot exists before we go on.
611 if not sysroot.Exists():
Alex Kleinb6847e22022-11-07 10:44:48 -0700612 logging.warning("The sysroot does not exist.")
613 return
Alex Klein2275d692019-04-23 16:04:12 -0600614
Alex Klein1699fab2022-09-08 08:46:06 -0600615 try:
616 results = artifacts.BundleSimpleChromeArtifacts(
617 chroot, sysroot, build_target, output_dir
618 )
619 except artifacts.Error as e:
Alex Kleinb6847e22022-11-07 10:44:48 -0700620 logging.warning(
Alex Klein1699fab2022-09-08 08:46:06 -0600621 "Error %s raised in BundleSimpleChromeArtifacts: %s", type(e), e
622 )
Alex Kleinb6847e22022-11-07 10:44:48 -0700623 return
Alex Klein2275d692019-04-23 16:04:12 -0600624
Alex Klein1699fab2022-09-08 08:46:06 -0600625 for file_name in results:
626 output_proto.artifacts.add().path = file_name
Alex Klein2275d692019-04-23 16:04:12 -0600627
628
Alex Kleinb6847e22022-11-07 10:44:48 -0700629def _BundleVmFilesResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600630 """Add test vm files to a successful response."""
631 output_proto.artifacts.add().path = os.path.join(
632 input_proto.output_dir, "f1.tar"
633 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700634
635
636@faux.success(_BundleVmFilesResponse)
637@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600638@validate.require("chroot.path", "test_results_dir", "output_dir")
639@validate.exists("output_dir")
Alex Klein231d2da2019-07-22 16:44:45 -0600640@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000641def BundleVmFiles(
642 input_proto: artifacts_pb2.BundleVmFilesRequest,
643 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600644 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700645) -> None:
646 """Tar VM disk and memory files."""
Alex Klein1699fab2022-09-08 08:46:06 -0600647 chroot = controller_util.ParseChroot(input_proto.chroot)
648 test_results_dir = input_proto.test_results_dir
649 output_dir = input_proto.output_dir
Alex Klein6504eca2019-04-18 15:37:56 -0600650
Alex Klein1699fab2022-09-08 08:46:06 -0600651 archives = artifacts.BundleVmFiles(chroot, test_results_dir, output_dir)
652 for archive in archives:
653 output_proto.artifacts.add().path = archive
654
Tiancong Wangc4805b72019-06-11 12:12:03 -0700655
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700656def _ExportCpeReportResponse(input_proto, output_proto, _config):
Alex Klein1699fab2022-09-08 08:46:06 -0600657 """Add test cpe results to a successful response."""
658 output_proto.artifacts.add().path = os.path.join(
659 input_proto.output_dir, "cpe_report.txt"
660 )
661 output_proto.artifacts.add().path = os.path.join(
662 input_proto.output_dir, "cpe_warnings.txt"
663 )
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700664
665
666@faux.success(_ExportCpeReportResponse)
667@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600668@validate.require("sysroot.path")
669@validate.exists("output_dir")
Alex Klein036833d2022-06-01 13:05:01 -0600670@validate.validation_complete
Alex Klein1699fab2022-09-08 08:46:06 -0600671def ExportCpeReport(
672 input_proto: artifacts_pb2.BundleRequest,
673 output_proto: artifacts_pb2.BundleResponse,
674 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700675) -> Optional[int]:
Alex Klein1699fab2022-09-08 08:46:06 -0600676 """Export a CPE report."""
677 chroot = controller_util.ParseChroot(input_proto.chroot)
678 sysroot = controller_util.ParseSysroot(input_proto.sysroot)
679 output_dir = input_proto.output_dir
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600680
Alex Klein1699fab2022-09-08 08:46:06 -0600681 if not sysroot.Exists(chroot=chroot):
682 logging.warning("Sysroot does not exist: %s", sysroot.path)
683 return
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600684
Alex Klein1699fab2022-09-08 08:46:06 -0600685 cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600686
Alex Klein1699fab2022-09-08 08:46:06 -0600687 output_proto.artifacts.add().path = cpe_result.report
688 output_proto.artifacts.add().path = cpe_result.warnings
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900689
690
Alex Kleinb6847e22022-11-07 10:44:48 -0700691def _BundleGceTarballResponse(input_proto, output_proto, _config) -> None:
Alex Klein1699fab2022-09-08 08:46:06 -0600692 """Add artifact tarball to a successful response."""
693 output_proto.artifacts.add().path = os.path.join(
694 input_proto.output_dir, constants.TEST_IMAGE_GCE_TAR
695 )
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900696
697
698@faux.success(_BundleGceTarballResponse)
699@faux.empty_error
Alex Klein1699fab2022-09-08 08:46:06 -0600700@validate.require("build_target.name", "output_dir")
701@validate.exists("output_dir")
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900702@validate.validation_complete
Varun Somani04dccd72021-10-09 01:06:11 +0000703def BundleGceTarball(
704 input_proto: artifacts_pb2.BundleRequest,
705 output_proto: artifacts_pb2.BundleResponse,
Alex Klein1699fab2022-09-08 08:46:06 -0600706 _config: "api_config.ApiConfig",
Alex Kleinb6847e22022-11-07 10:44:48 -0700707) -> Optional[int]:
708 """Bundle the test image into a tarball suitable for importing into GCE."""
Alex Klein1699fab2022-09-08 08:46:06 -0600709 target = input_proto.build_target.name
710 output_dir = input_proto.output_dir
711 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
712 if image_dir is None:
713 return None
Shao-Chuan Leea44dddc2020-10-30 17:16:55 +0900714
Alex Klein1699fab2022-09-08 08:46:06 -0600715 tarball = artifacts.BundleGceTarball(output_dir, image_dir)
716 output_proto.artifacts.add().path = tarball