blob: f3623faac80a30a36aa854849fc56fb91ea07d75 [file] [log] [blame]
Evan Hernandezd437b4e2019-03-25 13:48:30 -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"""Portage Binhost operations."""
7
8from __future__ import print_function
9
Michael Mortensenfc823882019-08-27 14:38:07 -060010import os
11import shutil
Evan Hernandezd437b4e2019-03-25 13:48:30 -060012import urlparse
13
Alex Klein231d2da2019-07-22 16:44:45 -060014from chromite.api import controller
Alex Klein2b236722019-06-19 15:44:26 -060015from chromite.api import validate
Alex Kleinaf0e0452019-06-03 18:10:01 -060016from chromite.api.controller import controller_util
Evan Hernandezd437b4e2019-03-25 13:48:30 -060017from chromite.api.gen.chromite.api import binhost_pb2
Alex Kleina471f682019-05-31 11:23:45 -060018from chromite.lib import build_target_util
LaMont Jonesc64ae212019-04-15 15:41:28 -060019from chromite.lib import constants
20from chromite.lib import cros_build_lib
Evan Hernandezd437b4e2019-03-25 13:48:30 -060021from chromite.lib import gs
Alex Kleinaf0e0452019-06-03 18:10:01 -060022from chromite.lib import sysroot_lib
Evan Hernandezd437b4e2019-03-25 13:48:30 -060023from chromite.service import binhost
24
Alex Kleinaf0e0452019-06-03 18:10:01 -060025_OVERLAY_TYPE_TO_NAME = {
26 binhost_pb2.OVERLAYTYPE_PUBLIC: constants.PUBLIC_OVERLAYS,
27 binhost_pb2.OVERLAYTYPE_PRIVATE: constants.PRIVATE_OVERLAYS,
28 binhost_pb2.OVERLAYTYPE_BOTH: constants.BOTH_OVERLAYS,
29 binhost_pb2.OVERLAYTYPE_NONE: None
30}
31
Evan Hernandezd437b4e2019-03-25 13:48:30 -060032
Alex Klein2b236722019-06-19 15:44:26 -060033@validate.require('build_target.name')
Alex Klein231d2da2019-07-22 16:44:45 -060034@validate.validation_complete
35def GetBinhosts(input_proto, output_proto, _config):
Alex Klein7e40d252019-06-10 09:01:32 -060036 """Get a list of binhosts."""
Alex Klein2b236722019-06-19 15:44:26 -060037 build_target = build_target_util.BuildTarget(input_proto.build_target.name)
Alex Klein7e40d252019-06-10 09:01:32 -060038
39 binhosts = binhost.GetBinhosts(build_target)
40
41 for current in binhosts:
42 new_binhost = output_proto.binhosts.add()
43 new_binhost.uri = current
Alex Kleind3ac0bd2019-06-10 15:17:51 -060044 new_binhost.package_index = 'Packages'
Alex Klein7e40d252019-06-10 09:01:32 -060045
46
Alex Klein2b236722019-06-19 15:44:26 -060047@validate.require('build_target.name')
Alex Klein231d2da2019-07-22 16:44:45 -060048@validate.validation_complete
49def GetPrivatePrebuiltAclArgs(input_proto, output_proto, _config):
Alex Kleina471f682019-05-31 11:23:45 -060050 """Get the ACL args from the files in the private overlays."""
Alex Klein2b236722019-06-19 15:44:26 -060051 build_target = build_target_util.BuildTarget(input_proto.build_target.name)
Alex Kleina471f682019-05-31 11:23:45 -060052
53 try:
54 args = binhost.GetPrebuiltAclArgs(build_target)
55 except binhost.Error as e:
56 cros_build_lib.Die(e.message)
57
58 for arg, value in args:
59 new_arg = output_proto.args.add()
60 new_arg.arg = arg
61 new_arg.value = value
62
63
Alex Klein231d2da2019-07-22 16:44:45 -060064@validate.require('uri')
65def PrepareBinhostUploads(input_proto, output_proto, config):
Evan Hernandezd437b4e2019-03-25 13:48:30 -060066 """Return a list of files to uplooad to the binhost.
67
68 See BinhostService documentation in api/proto/binhost.proto.
69
70 Args:
71 input_proto (PrepareBinhostUploadsRequest): The input proto.
72 output_proto (PrepareBinhostUploadsResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -060073 config (api_config.ApiConfig): The API call config.
Evan Hernandezd437b4e2019-03-25 13:48:30 -060074 """
Alex Kleinaf0e0452019-06-03 18:10:01 -060075 target_name = (input_proto.sysroot.build_target.name
76 or input_proto.build_target.name)
77 sysroot_path = input_proto.sysroot.path
Evan Hernandezd437b4e2019-03-25 13:48:30 -060078
Alex Kleinaf0e0452019-06-03 18:10:01 -060079 if not sysroot_path and not target_name:
80 cros_build_lib.Die('Sysroot.path is required.')
81
82 build_target = build_target_util.BuildTarget(target_name)
83 chroot = controller_util.ParseChroot(input_proto.chroot)
84
85 if not sysroot_path:
86 # Very temporary, so not worried about this not calling the lib function.
87 sysroot_path = build_target.root
88 sysroot = sysroot_lib.Sysroot(sysroot_path)
89
90 uri = input_proto.uri
Evan Hernandezd437b4e2019-03-25 13:48:30 -060091 # For now, we enforce that all input URIs are Google Storage buckets.
92 if not gs.PathIsGs(uri):
93 raise ValueError('Upload URI %s must be Google Storage.' % uri)
94
Alex Klein231d2da2019-07-22 16:44:45 -060095 if config.validate_only:
96 return controller.RETURN_CODE_VALID_INPUT
97
Evan Hernandezd437b4e2019-03-25 13:48:30 -060098 parsed_uri = urlparse.urlparse(uri)
Alex Klein8dffea42019-06-14 14:01:36 -060099 upload_uri = gs.GetGsURL(parsed_uri.netloc, for_gsutil=True).rstrip('/')
Alex Klein3e728442019-05-15 11:46:57 -0600100 upload_path = parsed_uri.path.lstrip('/')
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600101
102 # Read all packages and update the index. The index must be uploaded to the
103 # binhost for Portage to use it, so include it in upload_targets.
Alex Kleinaf0e0452019-06-03 18:10:01 -0600104 uploads_dir = binhost.GetPrebuiltsRoot(chroot, sysroot, build_target)
Alex Klein3e728442019-05-15 11:46:57 -0600105 index_path = binhost.UpdatePackageIndex(uploads_dir, upload_uri, upload_path,
106 sudo=True)
Alex Kleinb5d57a62019-06-20 12:04:53 -0600107 upload_targets = binhost.GetPrebuiltsFiles(uploads_dir)
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600108 assert index_path.startswith(uploads_dir), (
109 'expected index_path to start with uploads_dir')
110 upload_targets.append(index_path[len(uploads_dir):])
111
112 output_proto.uploads_dir = uploads_dir
113 for upload_target in upload_targets:
114 output_proto.upload_targets.add().path = upload_target.strip('/')
115
Michael Mortensenfc823882019-08-27 14:38:07 -0600116@validate.require('uri', 'sysroot.path')
117@validate.exists('uploads_dir')
118def PrepareDevInstallBinhostUploads(input_proto, output_proto, config):
119 """Return a list of files to upload to the binhost"
120
121 The files will also be copied to the uploads_dir.
122 See BinhostService documentation in api/proto/binhost.proto.
123
124 Args:
125 input_proto (PrepareDevInstallBinhostUploadsRequest): The input proto.
126 output_proto (PrepareDevInstallBinhostUploadsResponse): The output proto.
127 config (api_config.ApiConfig): The API call config.
128 """
129 sysroot_path = input_proto.sysroot.path
130
131 # build_target = build_target_util.BuildTarget(target_name)
132 chroot = controller_util.ParseChroot(input_proto.chroot)
133 sysroot = sysroot_lib.Sysroot(sysroot_path)
134
135 uri = input_proto.uri
136 # For now, we enforce that all input URIs are Google Storage buckets.
137 if not gs.PathIsGs(uri):
138 raise ValueError('Upload URI %s must be Google Storage.' % uri)
139
140 if config.validate_only:
141 return controller.RETURN_CODE_VALID_INPUT
142
143 parsed_uri = urlparse.urlparse(uri)
144 upload_uri = gs.GetGsURL(parsed_uri.netloc, for_gsutil=True).rstrip('/')
145 upload_path = parsed_uri.path.lstrip('/')
146
147 # Calculate the filename for the to-be-created Packages file, which will
148 # contain only devinstall packages.
149 devinstall_package_index_path = os.path.join(input_proto.uploads_dir,
150 'Packages')
151 upload_targets_list = binhost.ReadDevInstallFilesToCreatePackageIndex(
152 chroot, sysroot, devinstall_package_index_path, upload_uri, upload_path)
153
154 package_dir = chroot.full_path(sysroot.path, 'packages')
155 for upload_target in upload_targets_list:
156 # Copy each package to target/category/package
157 upload_target = upload_target.strip('/')
158 category = upload_target.split(os.sep)[0]
159 target_dir = os.path.join(input_proto.uploads_dir, category)
160 if not os.path.exists(target_dir):
161 os.makedirs(target_dir)
162 full_src_pkg_path = os.path.join(package_dir, upload_target)
163 full_target_src_path = os.path.join(input_proto.uploads_dir, upload_target)
164 shutil.copyfile(full_src_pkg_path, full_target_src_path)
165 output_proto.upload_targets.add().path = upload_target
166 output_proto.upload_targets.add().path = 'Packages'
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600167
Alex Klein231d2da2019-07-22 16:44:45 -0600168@validate.require('build_target.name', 'key', 'uri')
169@validate.validation_complete
170def SetBinhost(input_proto, output_proto, _config):
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600171 """Set the URI for a given binhost key and build target.
172
173 See BinhostService documentation in api/proto/binhost.proto.
174
175 Args:
176 input_proto (SetBinhostRequest): The input proto.
177 output_proto (SetBinhostResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600178 _config (api_config.ApiConfig): The API call config.
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600179 """
180 target = input_proto.build_target.name
181 key = binhost_pb2.BinhostKey.Name(input_proto.key)
182 uri = input_proto.uri
183 private = input_proto.private
Alex Klein6fb0eb82019-05-20 16:16:14 -0600184
185 # Temporary measure to force the new parallel cq post submit builders to write
186 # to a different file than the old ones. Writing to the same file was causing
187 # them to fight over the new one's value and the old logic of clearing out
188 # the values for files it didn't update. Once we've done a full switch over,
189 # we can dump this logic and delete all of the PARALLEL_POSTSUBMIT_BINHOST
190 # configs.
191 # TODO(crbug.com/965244) remove this.
192 if key == 'POSTSUBMIT_BINHOST':
193 key = 'PARALLEL_POSTSUBMIT_BINHOST'
194
Evan Hernandezd437b4e2019-03-25 13:48:30 -0600195 output_proto.output_file = binhost.SetBinhost(target, key, uri,
196 private=private)
LaMont Jonesc64ae212019-04-15 15:41:28 -0600197
LaMont Jonesc64ae212019-04-15 15:41:28 -0600198
Alex Klein231d2da2019-07-22 16:44:45 -0600199@validate.require('overlay_type')
200@validate.is_in('overlay_type', _OVERLAY_TYPE_TO_NAME)
201@validate.validation_complete
Alex Klein82c85d42019-08-14 15:47:51 -0600202def RegenBuildCache(input_proto, output_proto, _config):
LaMont Jonesc64ae212019-04-15 15:41:28 -0600203 """Regenerate the Build Cache for a build target.
204
205 See BinhostService documentation in api/proto/binhost.proto.
206
207 Args:
208 input_proto (RegenBuildCacheRequest): The input proto.
Alex Klein82c85d42019-08-14 15:47:51 -0600209 output_proto (RegenBuildCacheResponse): The output proto.
Alex Klein231d2da2019-07-22 16:44:45 -0600210 _config (api_config.ApiConfig): The API call config.
LaMont Jonesc64ae212019-04-15 15:41:28 -0600211 """
Alex Klein82c85d42019-08-14 15:47:51 -0600212 chroot = controller_util.ParseChroot(input_proto.chroot)
LaMont Jonesc64ae212019-04-15 15:41:28 -0600213 overlay_type = input_proto.overlay_type
Alex Klein82c85d42019-08-14 15:47:51 -0600214 overlays = binhost.RegenBuildCache(chroot,
215 _OVERLAY_TYPE_TO_NAME[overlay_type])
216
217 for overlay in overlays:
218 output_proto.modified_overlays.add().path = overlay