1# 2# Copyright (C) 2018 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the 'License'); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an 'AS IS' BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import logging 18import os 19 20from host_controller import common 21from host_controller.command_processor import base_command_processor 22 23 24class CommandFetch(base_command_processor.BaseCommandProcessor): 25 """Command processor for fetch command. 26 27 Attributes: 28 arg_parser: ConsoleArgumentParser object, argument parser. 29 console: cmd.Cmd console object. 30 command: string, command name which this processor will handle. 31 command_detail: string, detailed explanation for the command. 32 """ 33 34 command = "fetch" 35 command_detail = "Fetch a build artifact." 36 37 # @Override 38 def SetUp(self): 39 """Initializes the parser for fetch command.""" 40 self.arg_parser.add_argument( 41 '--type', 42 default='pab', 43 choices=('local_fs', 'gcs', 'pab', 'ab'), 44 help='Build provider type') 45 self.arg_parser.add_argument( 46 '--method', 47 default='GET', 48 choices=('GET', 'POST'), 49 help='Method for fetching') 50 self.arg_parser.add_argument( 51 "--path", # required for local_fs 52 help="The path of a local directory which keeps the artifacts.") 53 self.arg_parser.add_argument( 54 "--branch", # required for pab 55 help="Branch to grab the artifact from.") 56 self.arg_parser.add_argument( 57 "--target", # required for pab 58 help="Target product to grab the artifact from.") 59 # TODO(lejonathan): find a way to not specify this? 60 self.arg_parser.add_argument( 61 "--account_id", 62 default=common._DEFAULT_ACCOUNT_ID, 63 help="Partner Android Build account_id to use.") 64 self.arg_parser.add_argument( 65 '--build_id', 66 default='latest', 67 help='Build ID to use default latest.') 68 self.arg_parser.add_argument( 69 "--artifact_name", # required for pab 70 help= 71 "Name of the artifact to be fetched. {id} replaced with build id.") 72 self.arg_parser.add_argument( 73 "--userinfo-file", 74 help= 75 "Location of file containing email and password, if using POST.") 76 self.arg_parser.add_argument( 77 "--noauth_local_webserver", 78 default=False, 79 type=bool, 80 help="True to not use a local webserver for authentication.") 81 self.arg_parser.add_argument( 82 "--fetch_signed_build", 83 default=False, 84 type=bool, 85 help="True to fetch only signed build images.") 86 self.arg_parser.add_argument( 87 "--full_device_images", 88 default=False, 89 type=bool, 90 help="True to skip checking whether the fetched artifacts are " 91 "fully packaged device images.") 92 self.arg_parser.add_argument( 93 "--gsi", 94 default=False, 95 type=bool, 96 help="True if a target is GSI. Only system.img and " 97 "vbmeta.img are taken.") 98 self.arg_parser.add_argument( 99 "--set_suite_as", 100 default="", 101 choices=("", "vts", "cts", "gts", "sts"), 102 help="To specify the type of a test suite that is being fetched." 103 "Used when the artifact's file name does not follow the " 104 "standard naming convention.") 105 106 # @Override 107 def Run(self, arg_line): 108 """Makes the host download a build artifact from PAB.""" 109 args = self.arg_parser.ParseLine(arg_line) 110 111 if args.type not in self.console._build_provider: 112 logging.error("ERROR: uninitialized fetch type %s", args.type) 113 return False 114 115 provider = self.console._build_provider[args.type] 116 if args.type == "pab": 117 # do we want this somewhere else? No harm in doing multiple times 118 provider.Authenticate(args.userinfo_file, 119 args.noauth_local_webserver) 120 if not args.fetch_signed_build: 121 (device_images, test_suites, fetch_environment, 122 _) = provider.GetArtifact( 123 account_id=args.account_id, 124 branch=args.branch, 125 target=args.target, 126 artifact_name=args.artifact_name, 127 build_id=args.build_id, 128 method=args.method, 129 full_device_images=args.full_device_images) 130 self.console.fetch_info["fetch_signed_build"] = False 131 else: 132 (device_images, test_suites, fetch_environment, 133 _) = provider.GetSignedBuildArtifact( 134 account_id=args.account_id, 135 branch=args.branch, 136 target=args.target, 137 artifact_name=args.artifact_name, 138 build_id=args.build_id, 139 method=args.method, 140 full_device_images=args.full_device_images) 141 self.console.fetch_info["fetch_signed_build"] = True 142 143 self.console.fetch_info["build_id"] = fetch_environment["build_id"] 144 elif args.type == "local_fs": 145 device_images, test_suites = provider.Fetch( 146 args.path, args.full_device_images) 147 self.console.fetch_info["build_id"] = None 148 elif args.type == "gcs": 149 device_images, test_suites, tools = provider.Fetch( 150 args.path, args.full_device_images, args.set_suite_as) 151 self.console.fetch_info["build_id"] = None 152 elif args.type == "ab": 153 device_images, test_suites, fetch_environment = provider.Fetch( 154 branch=args.branch, 155 target=args.target, 156 artifact_name=args.artifact_name, 157 build_id=args.build_id, 158 full_device_images=args.full_device_images) 159 self.console.fetch_info["build_id"] = fetch_environment["build_id"] 160 else: 161 logging.error("ERROR: unknown fetch type %s", args.type) 162 return False 163 164 if args.gsi: 165 filtered_images = {} 166 image_names = device_images.keys() 167 for image_name in image_names: 168 if image_name.endswith(".img") and image_name not in [ 169 "system.img", "vbmeta.img" 170 ]: 171 provider.RemoveDeviceImage(image_name) 172 continue 173 filtered_images[image_name] = device_images[image_name] 174 device_images = filtered_images 175 176 if args.type == "gcs": 177 gcs_path, filename = os.path.split(args.path) 178 self.console.fetch_info["branch"] = gcs_path 179 self.console.fetch_info["target"] = filename 180 self.console.fetch_info["build_id"] = "latest" 181 self.console.fetch_info["account_id"] = "" 182 else: 183 self.console.fetch_info["branch"] = args.branch 184 self.console.fetch_info["target"] = args.target 185 self.console.fetch_info["account_id"] = args.account_id 186 187 self.console.UpdateFetchInfo(provider.GetFetchedArtifactType()) 188 189 self.console.device_image_info.update(device_images) 190 self.console.test_suite_info.update(test_suites) 191 self.console.tools_info.update(provider.GetAdditionalFile()) 192 193 if self.console.device_image_info: 194 logging.info("device images:\n%s", "\n".join( 195 image + ": " + path 196 for image, path in self.console.device_image_info.iteritems())) 197 if self.console.test_suite_info: 198 logging.info("test suites:\n%s", "\n".join( 199 suite + ": " + path 200 for suite, path in self.console.test_suite_info.iteritems())) 201 if self.console.tools_info: 202 logging.info("additional files:\n%s", "\n".join( 203 rel_path + ": " + full_path for rel_path, full_path in 204 self.console.tools_info.iteritems())) 205