blob: ba191b037c3fbbe5261dd0428a4efba817865068 [file] [log] [blame]
Evan Hernandezf388cbf2019-04-01 11:15:23 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Implements ArtifactService."""
7
8from __future__ import print_function
9
10import os
Mike Frysingeref94e4c2020-02-10 23:59:54 -050011import sys
Evan Hernandezf388cbf2019-04-01 11:15:23 -060012
Alex Klein231d2da2019-07-22 16:44:45 -060013from chromite.api import controller
Alex Klein076841b2019-08-29 15:19:39 -060014from chromite.api import faux
Alex Klein2b236722019-06-19 15:44:26 -060015from chromite.api import validate
Alex Klein238d8862019-05-07 11:32:46 -060016from chromite.api.controller import controller_util
Tiancong Wang24a3df72019-08-20 15:48:51 -070017from chromite.api.gen.chromite.api import toolchain_pb2
Evan Hernandezf388cbf2019-04-01 11:15:23 -060018from chromite.cbuildbot import commands
Alex Klein2275d692019-04-23 16:04:12 -060019from chromite.lib import chroot_lib
Evan Hernandezf388cbf2019-04-01 11:15:23 -060020from chromite.lib import constants
21from chromite.lib import cros_build_lib
Evan Hernandezde445982019-04-22 13:42:34 -060022from chromite.lib import cros_logging as logging
Alex Klein2275d692019-04-23 16:04:12 -060023from chromite.lib import sysroot_lib
24from chromite.service import artifacts
Evan Hernandezf388cbf2019-04-01 11:15:23 -060025
26
Mike Frysingeref94e4c2020-02-10 23:59:54 -050027assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
28
29
Evan Hernandez9f125ac2019-04-08 17:18:47 -060030def _GetImageDir(build_root, target):
31 """Return path containing images for the given build target.
32
Alex Kleine2612a02019-04-18 13:51:06 -060033 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
34
Evan Hernandez9f125ac2019-04-08 17:18:47 -060035 Args:
36 build_root (str): Path to checkout where build occurs.
37 target (str): Name of the build target.
38
39 Returns:
Alex Kleind2bf1462019-10-24 16:37:04 -060040 Path to the latest directory containing target images or None.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060041 """
42 image_dir = os.path.join(build_root, 'src/build/images', target, 'latest')
43 if not os.path.exists(image_dir):
Alex Kleind2bf1462019-10-24 16:37:04 -060044 logging.warning('Expected to find image output for target %s at %s, but '
45 'path does not exist', target, image_dir)
46 return None
47
Evan Hernandez9f125ac2019-04-08 17:18:47 -060048 return image_dir
49
50
Michael Mortensen2d6a2402019-11-26 13:40:40 -070051def _BundleImageArchivesResponse(input_proto, output_proto, _config):
52 """Add artifact paths to a successful response."""
53 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
54 'path0.tar.xz')
55 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
56 'path1.tar.xz')
57
58
59@faux.success(_BundleImageArchivesResponse)
60@faux.empty_error
Alex Kleind91e95a2019-09-17 10:39:02 -060061@validate.require('build_target.name')
62@validate.exists('output_dir')
63@validate.validation_complete
64def BundleImageArchives(input_proto, output_proto, _config):
65 """Create a .tar.xz archive for each image that has been created."""
66 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
67 output_dir = input_proto.output_dir
68 image_dir = _GetImageDir(constants.SOURCE_ROOT, build_target.name)
Alex Kleind2bf1462019-10-24 16:37:04 -060069 if image_dir is None:
70 return
Alex Kleind91e95a2019-09-17 10:39:02 -060071
72 archives = artifacts.ArchiveImages(image_dir, output_dir)
73
74 for archive in archives:
75 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
76
77
Michael Mortensen2d6a2402019-11-26 13:40:40 -070078def _BundleImageZipResponse(input_proto, output_proto, _config):
79 """Add artifact zip files to a successful response."""
80 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
81 'image.zip')
82
83
84@faux.success(_BundleImageZipResponse)
85@faux.empty_error
Michael Mortensen01910922019-07-24 14:48:10 -060086@validate.require('build_target.name', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -060087@validate.exists('output_dir')
88@validate.validation_complete
89def BundleImageZip(input_proto, output_proto, _config):
Evan Hernandez9f125ac2019-04-08 17:18:47 -060090 """Bundle image.zip.
91
92 Args:
93 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -060094 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -060095 _config (api_config.ApiConfig): The API call config.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060096 """
97 target = input_proto.build_target.name
98 output_dir = input_proto.output_dir
99 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
Alex Kleind2bf1462019-10-24 16:37:04 -0600100 if image_dir is None:
101 return None
Alex Klein231d2da2019-07-22 16:44:45 -0600102
Michael Mortensen01910922019-07-24 14:48:10 -0600103 archive = artifacts.BundleImageZip(output_dir, image_dir)
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600104 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
105
106
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700107def _BundleTestUpdatePayloadsResponse(input_proto, output_proto, _config):
108 """Add test payload files to a successful response."""
109 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
110 'payload1.bin')
111
112
113@faux.success(_BundleTestUpdatePayloadsResponse)
114@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600115@validate.require('build_target.name', 'output_dir')
116@validate.exists('output_dir')
117@validate.validation_complete
118def BundleTestUpdatePayloads(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600119 """Generate minimal update payloads for the build target for testing.
120
121 Args:
122 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600123 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600124 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600125 """
126 target = input_proto.build_target.name
127 output_dir = input_proto.output_dir
128 build_root = constants.SOURCE_ROOT
129
130 # Use the first available image to create the update payload.
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600131 img_dir = _GetImageDir(build_root, target)
Alex Kleind2bf1462019-10-24 16:37:04 -0600132 if img_dir is None:
133 return None
134
Alex Kleincb541e82019-06-26 15:06:11 -0600135 img_types = [constants.IMAGE_TYPE_TEST, constants.IMAGE_TYPE_DEV,
136 constants.IMAGE_TYPE_BASE]
137 img_names = [constants.IMAGE_TYPE_TO_NAME[t] for t in img_types]
Mike Frysinger66ce4132019-07-17 22:52:52 -0400138 img_paths = [os.path.join(img_dir, x) for x in img_names]
Mike Frysingera552be42018-08-17 14:39:32 -0400139 valid_images = [x for x in img_paths if os.path.exists(x)]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600140
Alex Kleincb541e82019-06-26 15:06:11 -0600141 if not valid_images:
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600142 cros_build_lib.Die(
143 'Expected to find an image of type among %r for target "%s" '
Evan Hernandez9f125ac2019-04-08 17:18:47 -0600144 'at path %s.', img_types, target, img_dir)
Alex Kleincb541e82019-06-26 15:06:11 -0600145 image = valid_images[0]
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600146
Alex Kleincb541e82019-06-26 15:06:11 -0600147 payloads = artifacts.BundleTestUpdatePayloads(image, output_dir)
148 for payload in payloads:
149 output_proto.artifacts.add().path = payload
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600150
151
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700152def _BundleAutotestFilesResponse(input_proto, output_proto, _config):
153 """Add test autotest files to a successful response."""
154 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
155 'autotest-a.tar.gz')
156
157
158@faux.success(_BundleAutotestFilesResponse)
159@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600160@validate.require('output_dir')
161@validate.exists('output_dir')
162def BundleAutotestFiles(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600163 """Tar the autotest files for a build target.
164
165 Args:
166 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600167 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600168 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600169 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600170 output_dir = input_proto.output_dir
Alex Klein238d8862019-05-07 11:32:46 -0600171 target = input_proto.build_target.name
Alex Kleine21a0952019-08-23 16:08:16 -0600172 chroot = controller_util.ParseChroot(input_proto.chroot)
173
Alex Klein238d8862019-05-07 11:32:46 -0600174 if target:
Alex Kleine21a0952019-08-23 16:08:16 -0600175 sysroot_path = os.path.join('/build', target)
Alex Klein238d8862019-05-07 11:32:46 -0600176 else:
177 # New style call, use chroot and sysroot.
Alex Klein238d8862019-05-07 11:32:46 -0600178 sysroot_path = input_proto.sysroot.path
179 if not sysroot_path:
180 cros_build_lib.Die('sysroot.path is required.')
181
Alex Kleine21a0952019-08-23 16:08:16 -0600182 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein238d8862019-05-07 11:32:46 -0600183
Alex Klein231d2da2019-07-22 16:44:45 -0600184 # TODO(saklein): Switch to the validate_only decorator when legacy handling
185 # is removed.
186 if config.validate_only:
187 return controller.RETURN_CODE_VALID_INPUT
188
Alex Kleine21a0952019-08-23 16:08:16 -0600189 if not sysroot.Exists(chroot=chroot):
Alex Klein238d8862019-05-07 11:32:46 -0600190 cros_build_lib.Die('Sysroot path must exist: %s', sysroot.path)
191
192 try:
193 # Note that this returns the full path to *multiple* tarballs.
Alex Kleine21a0952019-08-23 16:08:16 -0600194 archives = artifacts.BundleAutotestFiles(chroot, sysroot, output_dir)
Alex Klein238d8862019-05-07 11:32:46 -0600195 except artifacts.Error as e:
Mike Frysinger6b5c3cd2019-08-27 16:51:00 -0400196 cros_build_lib.Die(e)
Alex Klein238d8862019-05-07 11:32:46 -0600197
198 for archive in archives.values():
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600199 output_proto.artifacts.add().path = archive
200
201
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700202def _BundleTastFilesResponse(input_proto, output_proto, _config):
203 """Add test tast files to a successful response."""
204 output_proto.artifacts.add().path = os.path.join(input_proto.output_dir,
205 'tast_bundles.tar.gz')
206
207
208@faux.success(_BundleTastFilesResponse)
209@faux.empty_error
Alex Kleinb9d810b2019-07-01 12:38:02 -0600210@validate.require('output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600211@validate.exists('output_dir')
212def BundleTastFiles(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600213 """Tar the tast files for a build target.
214
215 Args:
216 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600217 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600218 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600219 """
220 target = input_proto.build_target.name
221 output_dir = input_proto.output_dir
222 build_root = constants.SOURCE_ROOT
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600223
Alex Kleinb9d810b2019-07-01 12:38:02 -0600224 chroot = controller_util.ParseChroot(input_proto.chroot)
225 sysroot_path = input_proto.sysroot.path
226
227 # TODO(saklein) Cleanup legacy handling after it has been switched over.
228 if target:
229 # Legacy handling.
Alex Klein171da612019-08-06 14:00:42 -0600230 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
Alex Kleinb9d810b2019-07-01 12:38:02 -0600231 sysroot_path = os.path.join('/build', target)
232
233 # New handling - chroot & sysroot based.
234 # TODO(saklein) Switch this to the require decorator when legacy is removed.
235 if not sysroot_path:
236 cros_build_lib.Die('sysroot.path is required.')
237
Alex Klein231d2da2019-07-22 16:44:45 -0600238 # TODO(saklein): Switch to the validation_complete decorator when legacy
239 # handling is removed.
240 if config.validate_only:
241 return controller.RETURN_CODE_VALID_INPUT
242
Alex Kleinb9d810b2019-07-01 12:38:02 -0600243 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -0600244 if not sysroot.Exists(chroot=chroot):
Alex Kleinb9d810b2019-07-01 12:38:02 -0600245 cros_build_lib.Die('Sysroot must exist.')
246
247 archive = artifacts.BundleTastFiles(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600248
LaMont Jonesb9793cd2020-06-11 08:14:46 -0600249 if archive:
250 output_proto.artifacts.add().path = archive
251 else:
252 logging.warning('Found no tast files for %s.', target)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600253
254
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700255def _BundlePinnedGuestImagesResponse(input_proto, output_proto, _config):
256 """Add test pinned guest image files to a successful response."""
257 output_proto.artifacts.add().path = os.path.join(
258 input_proto.output_dir, 'pinned-guest-images.tar.gz')
259
260
261@faux.success(_BundlePinnedGuestImagesResponse)
262@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600263@validate.require('build_target.name', 'output_dir')
264@validate.exists('output_dir')
265@validate.validation_complete
266def BundlePinnedGuestImages(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600267 """Tar the pinned guest images for a build target.
268
269 Args:
270 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600271 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600272 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600273 """
274 target = input_proto.build_target.name
275 output_dir = input_proto.output_dir
276 build_root = constants.SOURCE_ROOT
277
Alex Kleine2612a02019-04-18 13:51:06 -0600278 # TODO(crbug.com/954299): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600279 archive = commands.BuildPinnedGuestImagesTarball(build_root, target,
280 output_dir)
281
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600282 if archive is None:
Evan Hernandezde445982019-04-22 13:42:34 -0600283 logging.warning('Found no pinned guest images for %s.', target)
284 return
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600285
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600286 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
287
288
Alex Kleinc3e8d0c2020-05-15 11:20:22 -0600289def _FetchPinnedGuestImageUrisResponse(_input_proto, output_proto, _config):
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700290 """Add test fetched pinned guest image files to a successful response."""
291 pinned_image = output_proto.pinned_images.add()
292 pinned_image.filename = 'pinned_file.tar.gz'
293 pinned_image.uri = 'https://testuri.com'
294
295
Alex Kleinc3e8d0c2020-05-15 11:20:22 -0600296@faux.success(_FetchPinnedGuestImageUrisResponse)
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700297@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600298@validate.require('sysroot.path')
299@validate.validation_complete
Alex Kleinc3e8d0c2020-05-15 11:20:22 -0600300def FetchPinnedGuestImageUris(input_proto, output_proto, _config):
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600301 """Get the pinned guest image information."""
302 sysroot_path = input_proto.sysroot.path
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600303
304 chroot = controller_util.ParseChroot(input_proto.chroot)
305 sysroot = sysroot_lib.Sysroot(sysroot_path)
306
307 if not chroot.exists():
308 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
Alex Klein231d2da2019-07-22 16:44:45 -0600309 elif not sysroot.Exists(chroot=chroot):
Alex Klein7bf0ecb2019-06-25 10:04:15 -0600310 cros_build_lib.Die('Sysroot does not exist: %s',
311 chroot.full_path(sysroot.path))
312
313 pins = artifacts.FetchPinnedGuestImages(chroot, sysroot)
314
315 for pin in pins:
316 pinned_image = output_proto.pinned_images.add()
317 pinned_image.filename = pin.filename
318 pinned_image.uri = pin.uri
319
320
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700321def _BundleFirmwareResponse(input_proto, output_proto, _config):
322 """Add test firmware image files to a successful response."""
323 output_proto.artifacts.add().path = os.path.join(
324 input_proto.output_dir, 'firmware.tar.gz')
325
326
327@faux.success(_BundleFirmwareResponse)
328@faux.empty_error
Michael Mortensen38675192019-06-28 16:52:55 +0000329@validate.require('output_dir', 'sysroot.path')
Alex Klein231d2da2019-07-22 16:44:45 -0600330@validate.exists('output_dir')
331@validate.validation_complete
332def BundleFirmware(input_proto, output_proto, _config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600333 """Tar the firmware images for a build target.
334
335 Args:
336 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600337 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600338 _config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600339 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600340 output_dir = input_proto.output_dir
Michael Mortensen38675192019-06-28 16:52:55 +0000341 chroot = controller_util.ParseChroot(input_proto.chroot)
342 sysroot_path = input_proto.sysroot.path
343 sysroot = sysroot_lib.Sysroot(sysroot_path)
Alex Klein231d2da2019-07-22 16:44:45 -0600344
345 if not chroot.exists():
346 cros_build_lib.Die('Chroot does not exist: %s', chroot.path)
347 elif not sysroot.Exists(chroot=chroot):
348 cros_build_lib.Die('Sysroot does not exist: %s',
349 chroot.full_path(sysroot.path))
350
Michael Mortensen38675192019-06-28 16:52:55 +0000351 archive = artifacts.BuildFirmwareArchive(chroot, sysroot, output_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600352
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600353 if archive is None:
354 cros_build_lib.Die(
Michael Mortensen38675192019-06-28 16:52:55 +0000355 'Could not create firmware archive. No firmware found for %s.',
356 sysroot_path)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600357
Alex Klein231d2da2019-07-22 16:44:45 -0600358 output_proto.artifacts.add().path = archive
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600359
360
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700361def _BundleEbuildLogsResponse(input_proto, output_proto, _config):
362 """Add test log files to a successful response."""
363 output_proto.artifacts.add().path = os.path.join(
364 input_proto.output_dir, 'ebuild-logs.tar.gz')
365
366
367@faux.success(_BundleEbuildLogsResponse)
368@faux.empty_error
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600369@validate.exists('output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600370def BundleEbuildLogs(input_proto, output_proto, config):
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600371 """Tar the ebuild logs for a build target.
372
373 Args:
374 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600375 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600376 config (api_config.ApiConfig): The API call config.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600377 """
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600378 output_dir = input_proto.output_dir
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600379 sysroot_path = input_proto.sysroot.path
380 chroot = controller_util.ParseChroot(input_proto.chroot)
Evan Hernandeza478d802019-04-08 15:08:24 -0600381
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600382 # TODO(mmortensen) Cleanup legacy handling after it has been switched over.
383 target = input_proto.build_target.name
384 if target:
385 # Legacy handling.
386 build_root = constants.SOURCE_ROOT
Alex Klein171da612019-08-06 14:00:42 -0600387 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600388 sysroot_path = os.path.join('/build', target)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600389
Alex Klein231d2da2019-07-22 16:44:45 -0600390 # TODO(saklein): Switch to validation_complete decorator after legacy
391 # handling has been cleaned up.
392 if config.validate_only:
393 return controller.RETURN_CODE_VALID_INPUT
394
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600395 sysroot = sysroot_lib.Sysroot(sysroot_path)
396 archive = artifacts.BundleEBuildLogsTarball(chroot, sysroot, output_dir)
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600397 if archive is None:
398 cros_build_lib.Die(
Michael Mortensen3f382cb2019-07-29 13:21:49 -0600399 'Could not create ebuild logs archive. No logs found for %s.',
400 sysroot.path)
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600401 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600402
403
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700404def _BundleChromeOSConfigResponse(input_proto, output_proto, _config):
405 """Add test config files to a successful response."""
406 output_proto.artifacts.add().path = os.path.join(
407 input_proto.output_dir, 'config.yaml')
408
409
410@faux.success(_BundleChromeOSConfigResponse)
411@faux.empty_error
Andrew Lamb811aead2019-08-12 10:25:05 -0600412@validate.exists('output_dir')
413@validate.validation_complete
414def BundleChromeOSConfig(input_proto, output_proto, _config):
415 """Output the ChromeOS Config payload for a build target.
416
417 Args:
418 input_proto (BundleRequest): The input proto.
419 output_proto (BundleResponse): The output proto.
420 _config (api_config.ApiConfig): The API call config.
421 """
422 output_dir = input_proto.output_dir
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600423 sysroot_path = input_proto.sysroot.path
Andrew Lamb811aead2019-08-12 10:25:05 -0600424 chroot = controller_util.ParseChroot(input_proto.chroot)
425
Andrew Lamb67bd68f2019-08-15 09:09:15 -0600426 # TODO(mmortensen) Cleanup legacy handling after it has been switched over.
427 target = input_proto.build_target.name
428 if target:
429 # Legacy handling.
430 build_root = constants.SOURCE_ROOT
431 chroot = chroot_lib.Chroot(path=os.path.join(build_root, 'chroot'))
432 sysroot_path = os.path.join('/build', target)
433
434 sysroot = sysroot_lib.Sysroot(sysroot_path)
Andrew Lamb811aead2019-08-12 10:25:05 -0600435 chromeos_config = artifacts.BundleChromeOSConfig(chroot, sysroot, output_dir)
436 if chromeos_config is None:
437 cros_build_lib.Die(
438 'Could not create ChromeOS Config payload. No config found for %s.',
439 sysroot.path)
440 output_proto.artifacts.add().path = os.path.join(output_dir, chromeos_config)
441
442
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700443def _BundleSimpleChromeArtifactsResponse(input_proto, output_proto, _config):
444 """Add test simple chrome files to a successful response."""
445 output_proto.artifacts.add().path = os.path.join(
446 input_proto.output_dir, 'simple_chrome.txt')
447
448
449@faux.success(_BundleSimpleChromeArtifactsResponse)
450@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600451@validate.require('output_dir', 'sysroot.build_target.name', 'sysroot.path')
452@validate.exists('output_dir')
453@validate.validation_complete
454def BundleSimpleChromeArtifacts(input_proto, output_proto, _config):
Alex Klein2275d692019-04-23 16:04:12 -0600455 """Create the simple chrome artifacts."""
Alex Klein2275d692019-04-23 16:04:12 -0600456 sysroot_path = input_proto.sysroot.path
Alex Klein2275d692019-04-23 16:04:12 -0600457 output_dir = input_proto.output_dir
458
Alex Klein2275d692019-04-23 16:04:12 -0600459 # Build out the argument instances.
Alex Klein26e472b2020-03-10 14:35:01 -0600460 build_target = controller_util.ParseBuildTarget(
461 input_proto.sysroot.build_target)
462 chroot = controller_util.ParseChroot(input_proto.chroot)
Alex Klein2275d692019-04-23 16:04:12 -0600463 # Sysroot.path needs to be the fully qualified path, including the chroot.
464 full_sysroot_path = os.path.join(chroot.path, sysroot_path.lstrip(os.sep))
465 sysroot = sysroot_lib.Sysroot(full_sysroot_path)
466
467 # Quick sanity check that the sysroot exists before we go on.
468 if not sysroot.Exists():
469 cros_build_lib.Die('The sysroot does not exist.')
470
471 try:
472 results = artifacts.BundleSimpleChromeArtifacts(chroot, sysroot,
473 build_target, output_dir)
474 except artifacts.Error as e:
475 cros_build_lib.Die('Error %s raised in BundleSimpleChromeArtifacts: %s',
476 type(e), e)
477
478 for file_name in results:
479 output_proto.artifacts.add().path = file_name
480
481
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700482def _BundleVmFilesResponse(input_proto, output_proto, _config):
483 """Add test vm files to a successful response."""
484 output_proto.artifacts.add().path = os.path.join(
485 input_proto.output_dir, 'f1.tar')
486
487
488@faux.success(_BundleVmFilesResponse)
489@faux.empty_error
Michael Mortensen51f06722019-07-18 09:55:50 -0600490@validate.require('chroot.path', 'test_results_dir', 'output_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600491@validate.exists('output_dir')
492@validate.validation_complete
493def BundleVmFiles(input_proto, output_proto, _config):
Alex Klein6504eca2019-04-18 15:37:56 -0600494 """Tar VM disk and memory files.
495
496 Args:
Trent Begin008cade2019-10-31 13:40:59 -0600497 input_proto (BundleVmFilesRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600498 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600499 _config (api_config.ApiConfig): The API call config.
Alex Klein6504eca2019-04-18 15:37:56 -0600500 """
Michael Mortensen51f06722019-07-18 09:55:50 -0600501 chroot = controller_util.ParseChroot(input_proto.chroot)
502 test_results_dir = input_proto.test_results_dir
Alex Klein6504eca2019-04-18 15:37:56 -0600503 output_dir = input_proto.output_dir
504
Michael Mortensen51f06722019-07-18 09:55:50 -0600505 archives = artifacts.BundleVmFiles(
506 chroot, test_results_dir, output_dir)
Alex Klein6504eca2019-04-18 15:37:56 -0600507 for archive in archives:
508 output_proto.artifacts.add().path = archive
Tiancong Wangc4805b72019-06-11 12:12:03 -0700509
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700510def _BundleAFDOGenerationArtifactsResponse(input_proto, output_proto, _config):
511 """Add test tarball AFDO file to a successful response."""
512 output_proto.artifacts.add().path = os.path.join(
513 input_proto.output_dir, 'artifact1')
514
Alex Klein231d2da2019-07-22 16:44:45 -0600515
Tiancong Wang24a3df72019-08-20 15:48:51 -0700516_VALID_ARTIFACT_TYPES = [toolchain_pb2.BENCHMARK_AFDO,
517 toolchain_pb2.ORDERFILE]
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700518@faux.success(_BundleAFDOGenerationArtifactsResponse)
519@faux.empty_error
Alex Klein231d2da2019-07-22 16:44:45 -0600520@validate.require('build_target.name', 'output_dir')
Tiancong Wang50b80a92019-08-01 14:46:15 -0700521@validate.is_in('artifact_type', _VALID_ARTIFACT_TYPES)
Alex Klein231d2da2019-07-22 16:44:45 -0600522@validate.exists('output_dir')
Tiancong Wang2ade7932019-09-27 14:15:40 -0700523@validate.exists('chroot.chrome_dir')
Alex Klein231d2da2019-07-22 16:44:45 -0600524@validate.validation_complete
Tiancong Wang50b80a92019-08-01 14:46:15 -0700525def BundleAFDOGenerationArtifacts(input_proto, output_proto, _config):
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700526 """Generic function for creating tarballs of both AFDO and orderfile.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700527
528 Args:
Tiancong Wang50b80a92019-08-01 14:46:15 -0700529 input_proto (BundleChromeAFDORequest): The input proto.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700530 output_proto (BundleResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600531 _config (api_config.ApiConfig): The API call config.
Tiancong Wangc4805b72019-06-11 12:12:03 -0700532 """
Tiancong Wang2ade7932019-09-27 14:15:40 -0700533 chrome_root = input_proto.chroot.chrome_dir
Tiancong Wangc4805b72019-06-11 12:12:03 -0700534 output_dir = input_proto.output_dir
Tiancong Wang50b80a92019-08-01 14:46:15 -0700535 artifact_type = input_proto.artifact_type
Tiancong Wangc4805b72019-06-11 12:12:03 -0700536
Alex Klein26e472b2020-03-10 14:35:01 -0600537 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700538 chroot = controller_util.ParseChroot(input_proto.chroot)
539
540 try:
Tiancong Wang24a3df72019-08-20 15:48:51 -0700541 is_orderfile = bool(artifact_type is toolchain_pb2.ORDERFILE)
Tiancong Wang50b80a92019-08-01 14:46:15 -0700542 results = artifacts.BundleAFDOGenerationArtifacts(
Tiancong Wang2ade7932019-09-27 14:15:40 -0700543 is_orderfile, chroot, chrome_root,
Tiancong Wang50b80a92019-08-01 14:46:15 -0700544 build_target, output_dir)
Tiancong Wangc4805b72019-06-11 12:12:03 -0700545 except artifacts.Error as e:
546 cros_build_lib.Die('Error %s raised in BundleSimpleChromeArtifacts: %s',
547 type(e), e)
548
549 for file_name in results:
550 output_proto.artifacts.add().path = file_name
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600551
552
Michael Mortensen2d6a2402019-11-26 13:40:40 -0700553def _ExportCpeReportResponse(input_proto, output_proto, _config):
554 """Add test cpe results to a successful response."""
555 output_proto.artifacts.add().path = os.path.join(
556 input_proto.output_dir, 'cpe_report.txt')
557 output_proto.artifacts.add().path = os.path.join(
558 input_proto.output_dir, 'cpe_warnings.txt')
559
560
561@faux.success(_ExportCpeReportResponse)
562@faux.empty_error
Alex Klein0b1cbfc2019-08-14 10:09:58 -0600563@validate.exists('output_dir')
564def ExportCpeReport(input_proto, output_proto, config):
565 """Export a CPE report.
566
567 Args:
568 input_proto (BundleRequest): The input proto.
569 output_proto (BundleResponse): The output proto.
570 config (api_config.ApiConfig): The API call config.
571 """
572 chroot = controller_util.ParseChroot(input_proto.chroot)
573 output_dir = input_proto.output_dir
574
575 if input_proto.build_target.name:
576 # Legacy handling - use the default sysroot path for the build target.
577 build_target = controller_util.ParseBuildTarget(input_proto.build_target)
578 sysroot = sysroot_lib.Sysroot(build_target.root)
579 elif input_proto.sysroot.path:
580 sysroot = sysroot_lib.Sysroot(input_proto.sysroot.path)
581 else:
582 # TODO(saklein): Switch to validate decorators once legacy handling can be
583 # cleaned up.
584 cros_build_lib.Die('sysroot.path is required.')
585
586 if config.validate_only:
587 return controller.RETURN_CODE_VALID_INPUT
588
589 cpe_result = artifacts.GenerateCpeReport(chroot, sysroot, output_dir)
590
591 output_proto.artifacts.add().path = cpe_result.report
592 output_proto.artifacts.add().path = cpe_result.warnings