blob: 940c2083c6f29f1dc18b04340c5169da5d76292f [file] [log] [blame]
Evan Hernandezf388cbf2019-04-01 11:15:23 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Implements ArtifactService."""
7
8from __future__ import print_function
9
10import os
11
12from chromite.cbuildbot import commands
Alex Klein6504eca2019-04-18 15:37:56 -060013from chromite.cbuildbot.stages import vm_test_stages
Evan Hernandezf388cbf2019-04-01 11:15:23 -060014from chromite.lib import constants
15from chromite.lib import cros_build_lib
Evan Hernandezde445982019-04-22 13:42:34 -060016from chromite.lib import cros_logging as logging
Evan Hernandezf388cbf2019-04-01 11:15:23 -060017from chromite.lib import osutils
18
19
Evan Hernandez9f125ac2019-04-08 17:18:47 -060020def _GetImageDir(build_root, target):
21 """Return path containing images for the given build target.
22
Alex Kleine2612a02019-04-18 13:51:06 -060023 TODO(saklein) Expand image_lib.GetLatestImageLink to support this use case.
24
Evan Hernandez9f125ac2019-04-08 17:18:47 -060025 Args:
26 build_root (str): Path to checkout where build occurs.
27 target (str): Name of the build target.
28
29 Returns:
30 Path to the directory containing target images.
31
32 Raises:
33 DieSystemExit: If the image dir does not exist.
34 """
35 image_dir = os.path.join(build_root, 'src/build/images', target, 'latest')
36 if not os.path.exists(image_dir):
37 cros_build_lib.Die('Expected to find image output for target %s at %s, '
38 'but path does not exist' % (target, image_dir))
39 return image_dir
40
41
42def BundleImageZip(input_proto, output_proto):
43 """Bundle image.zip.
44
45 Args:
46 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -060047 output_proto (BundleResponse): The output proto.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060048 """
49 target = input_proto.build_target.name
50 output_dir = input_proto.output_dir
51 image_dir = _GetImageDir(constants.SOURCE_ROOT, target)
52 archive = commands.BuildImageZip(output_dir, image_dir)
53 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
54
55
Evan Hernandezf388cbf2019-04-01 11:15:23 -060056def BundleTestUpdatePayloads(input_proto, output_proto):
57 """Generate minimal update payloads for the build target for testing.
58
59 Args:
60 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -060061 output_proto (BundleResponse): The output proto.
Evan Hernandezf388cbf2019-04-01 11:15:23 -060062 """
63 target = input_proto.build_target.name
64 output_dir = input_proto.output_dir
65 build_root = constants.SOURCE_ROOT
66
67 # Use the first available image to create the update payload.
Evan Hernandez9f125ac2019-04-08 17:18:47 -060068 img_dir = _GetImageDir(build_root, target)
Evan Hernandezf388cbf2019-04-01 11:15:23 -060069 img_types = [
70 constants.IMAGE_TYPE_TEST, constants.IMAGE_TYPE_DEV,
71 constants.IMAGE_TYPE_BASE
72 ]
73 img_paths = []
74 for img_type in img_types:
Evan Hernandez9f125ac2019-04-08 17:18:47 -060075 img_path = os.path.join(img_dir, constants.IMAGE_TYPE_TO_NAME[img_type])
Evan Hernandezf388cbf2019-04-01 11:15:23 -060076 if os.path.exists(img_path):
77 img_paths.append(img_path)
78
79 if not img_paths:
80 cros_build_lib.Die(
81 'Expected to find an image of type among %r for target "%s" '
Evan Hernandez9f125ac2019-04-08 17:18:47 -060082 'at path %s.', img_types, target, img_dir)
Evan Hernandezf388cbf2019-04-01 11:15:23 -060083 img = img_paths[0]
84
85 # Unfortunately, the relevant commands.py functions do not return
86 # a list of generated files. As a workaround, we have commands.py
87 # put the files in a separate temporary directory so we can catalog them,
88 # then move them to the output dir.
Alex Kleine2612a02019-04-18 13:51:06 -060089 # TODO(crbug.com/954283): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -060090 with osutils.TempDir() as temp:
91 commands.GeneratePayloads(img, temp, full=True, stateful=True, delta=True)
92 commands.GenerateQuickProvisionPayloads(img, temp)
93 for path in osutils.DirectoryIterator(temp):
94 if os.path.isfile(path):
95 rel_path = os.path.relpath(path, temp)
96 output_proto.artifacts.add().path = os.path.join(output_dir, rel_path)
Evan Hernandezb04e2aa2019-04-08 16:55:54 -060097 osutils.CopyDirContents(temp, output_dir, allow_nonempty=True)
Evan Hernandezf388cbf2019-04-01 11:15:23 -060098
99
100def BundleAutotestFiles(input_proto, output_proto):
101 """Tar the autotest files for a build target.
102
103 Args:
104 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600105 output_proto (BundleResponse): The output proto.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600106 """
107 target = input_proto.build_target.name
108 output_dir = input_proto.output_dir
109 build_root = constants.SOURCE_ROOT
Evan Hernandez36589c62019-04-05 18:14:42 -0600110 cwd = os.path.join(build_root, 'chroot/build', target, 'usr/local/build')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600111
112 # Note that unlike the functions below, this returns the full path
113 # to *multiple* tarballs.
Alex Kleine2612a02019-04-18 13:51:06 -0600114 # TODO(crbug.com/954289): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600115 archives = commands.BuildAutotestTarballsForHWTest(build_root, cwd,
116 output_dir)
117
118 for archive in archives:
119 output_proto.artifacts.add().path = archive
120
121
122def BundleTastFiles(input_proto, output_proto):
123 """Tar the tast files for a build target.
124
125 Args:
126 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600127 output_proto (BundleResponse): The output proto.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600128 """
129 target = input_proto.build_target.name
130 output_dir = input_proto.output_dir
131 build_root = constants.SOURCE_ROOT
Evan Hernandez36589c62019-04-05 18:14:42 -0600132 cwd = os.path.join(build_root, 'chroot/build', target, 'build')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600133
134 # Note that unlike the functions below, this returns the full path
135 # to the tarball.
Alex Kleine2612a02019-04-18 13:51:06 -0600136 # TODO(crbug.com/954294): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600137 archive = commands.BuildTastBundleTarball(build_root, cwd, output_dir)
138
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600139 if archive is None:
140 cros_build_lib.Die(
141 'Could not bundle Tast files. '
142 'No Tast directories found for %s.', target)
143
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600144 output_proto.artifacts.add().path = archive
145
146
147def BundlePinnedGuestImages(input_proto, output_proto):
148 """Tar the pinned guest images for a build target.
149
150 Args:
151 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600152 output_proto (BundleResponse): The output proto.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600153 """
154 target = input_proto.build_target.name
155 output_dir = input_proto.output_dir
156 build_root = constants.SOURCE_ROOT
157
Alex Kleine2612a02019-04-18 13:51:06 -0600158 # TODO(crbug.com/954299): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600159 archive = commands.BuildPinnedGuestImagesTarball(build_root, target,
160 output_dir)
161
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600162 if archive is None:
Evan Hernandezde445982019-04-22 13:42:34 -0600163 logging.warning('Found no pinned guest images for %s.', target)
164 return
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600165
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600166 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
167
168
169def BundleFirmware(input_proto, output_proto):
170 """Tar the firmware images for a build target.
171
172 Args:
173 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600174 output_proto (BundleResponse): The output proto.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600175 """
176 target = input_proto.build_target.name
177 output_dir = input_proto.output_dir
178 build_root = constants.SOURCE_ROOT
179
Alex Kleine2612a02019-04-18 13:51:06 -0600180 # TODO(crbug.com/954300): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600181 archive = commands.BuildFirmwareArchive(build_root, target, output_dir)
182
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600183 if archive is None:
184 cros_build_lib.Die(
185 'Could not create firmware archive. No firmware found for %s.', target)
186
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600187 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
188
189
190def BundleEbuildLogs(input_proto, output_proto):
191 """Tar the ebuild logs for a build target.
192
193 Args:
194 input_proto (BundleRequest): The input proto.
Alex Klein6504eca2019-04-18 15:37:56 -0600195 output_proto (BundleResponse): The output proto.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600196 """
197 target = input_proto.build_target.name
198 output_dir = input_proto.output_dir
Evan Hernandeza478d802019-04-08 15:08:24 -0600199
200 # commands.BuildEbuildLogsTarball conflates "buildroot" with sysroot.
201 # Adjust accordingly...
202 build_root = os.path.join(constants.SOURCE_ROOT, 'chroot', 'build')
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600203
Alex Kleine2612a02019-04-18 13:51:06 -0600204 # TODO(crbug.com/954303): Replace with a chromite/service implementation.
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600205 archive = commands.BuildEbuildLogsTarball(build_root, target, output_dir)
206
Evan Hernandez9a5d3122019-04-09 10:51:23 -0600207 if archive is None:
208 cros_build_lib.Die(
209 'Could not create ebuild logs archive. No logs found for %s.', target)
210
Evan Hernandezf388cbf2019-04-01 11:15:23 -0600211 output_proto.artifacts.add().path = os.path.join(output_dir, archive)
Alex Klein6504eca2019-04-18 15:37:56 -0600212
213
214def BundleVmFiles(input_proto, output_proto):
215 """Tar VM disk and memory files.
216
217 Args:
218 input_proto (SysrootBundleRequest): The input proto.
219 output_proto (BundleResponse): The output proto.
220 """
221 chroot = input_proto.chroot.path
222 sysroot = input_proto.sysroot.path
223 test_results_dir = input_proto.test_results_dir
224 output_dir = input_proto.output_dir
225
226 if not chroot:
227 cros_build_lib.Die('chroot.path is required.')
228 if not sysroot:
229 cros_build_lib.Die('sysroot.path is required.')
230 if not test_results_dir:
231 cros_build_lib.Die('test_results_dir is required.')
232 if not output_dir:
233 cros_build_lib.Die('output_dir is required.')
234
235 # TODO(crbug.com/954344): Replace with a chromite/service implementation.
236 sysroot = sysroot.lstrip(os.sep)
237 result_dir = test_results_dir.lstrip(os.sep)
238 image_dir = os.path.join(chroot, sysroot, result_dir)
239 archives = vm_test_stages.ArchiveVMFilesFromImageDir(image_dir, output_dir)
240 for archive in archives:
241 output_proto.artifacts.add().path = archive