1#!/usr/bin/env python3 2# 3# Copyright 2018 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import os 18from acts.controllers.fuchsia_lib.ssh import FuchsiaSSHError 19 20 21def http_file_download_by_curl(fd, 22 url, 23 out_path='/tmp/', 24 curl_loc='/bin/curl', 25 remove_file_after_check=True, 26 timeout=3600, 27 limit_rate=None, 28 additional_args=None, 29 retry=3): 30 """Download http file by ssh curl. 31 32 Args: 33 fd: Fuchsia Device Object. 34 url: The url that file to be downloaded from. 35 out_path: Optional. Where to download file to. 36 out_path is /tmp by default. 37 curl_loc: Location of curl binary on fd. 38 remove_file_after_check: Whether to remove the downloaded file after 39 check. 40 timeout: timeout for file download to complete. 41 limit_rate: download rate in bps. None, if do not apply rate limit. 42 additional_args: Any additional args for curl. 43 retry: the retry request times provided in curl command. 44 """ 45 file_directory, file_name = _generate_file_directory_and_file_name( 46 url, out_path) 47 file_path = os.path.join(file_directory, file_name) 48 curl_cmd = curl_loc 49 if limit_rate: 50 curl_cmd += f' --limit-rate {limit_rate}' 51 if retry: 52 curl_cmd += f' --retry {retry}' 53 if additional_args: 54 curl_cmd += f' {additional_args}' 55 curl_cmd += f' --url {url} > {file_path}' 56 57 fd.log.info(f'Download {url} to {file_path} by ssh command {curl_cmd}') 58 try: 59 fd.ssh.run(curl_cmd, timeout_sec=timeout) 60 if _check_file_existence(fd, file_path): 61 fd.log.info(f'{url} is downloaded to {file_path} successfully') 62 return True 63 64 fd.log.warning(f'Fail to download {url}') 65 return False 66 except FuchsiaSSHError as e: 67 fd.log.warning(f'Command "{curl_cmd}" failed with error {e}') 68 return False 69 except Exception as e: 70 fd.log.error(f'Download {url} failed with unexpected exception {e}') 71 return False 72 finally: 73 if remove_file_after_check: 74 fd.log.info(f'Remove the downloaded file {file_path}') 75 try: 76 fd.ssh.run(f'rm {file_path}') 77 except FuchsiaSSHError: 78 pass 79 80 81def _generate_file_directory_and_file_name(url, out_path): 82 """Splits the file from the url and specifies the appropriate location of 83 where to store the downloaded file. 84 85 Args: 86 url: A url to the file that is going to be downloaded. 87 out_path: The location of where to store the file that is downloaded. 88 89 Returns: 90 file_directory: The directory of where to store the downloaded file. 91 file_name: The name of the file that is being downloaded. 92 """ 93 file_name = url.split('/')[-1] 94 if not out_path: 95 file_directory = '/tmp/' 96 elif not out_path.endswith('/'): 97 file_directory, file_name = os.path.split(out_path) 98 else: 99 file_directory = out_path 100 return file_directory, file_name 101 102 103def _check_file_existence(fd, file_path): 104 """Check file existence by file_path. If expected_file_size 105 is provided, then also check if the file meet the file size requirement. 106 107 Args: 108 fd: A fuchsia device 109 file_path: Where to store the file on the fuchsia device. 110 """ 111 try: 112 result = fd.ssh.run(f'ls -al "{file_path}"') 113 fd.log.debug(f'File {file_path} exists.') 114 return True 115 except FuchsiaSSHError as e: 116 if 'No such file or directory' in e.result.stderr: 117 fd.log.debug(f'File {file_path} does not exist.') 118 return False 119 raise e 120