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 18 19from acts.libs.proc.job import Error 20 21 22def http_file_download_by_curl(fd, 23 url, 24 out_path='/tmp/', 25 curl_loc='/bin/curl', 26 remove_file_after_check=True, 27 timeout=3600, 28 limit_rate=None, 29 additional_args=None, 30 retry=3): 31 """Download http file by ssh curl. 32 33 Args: 34 fd: Fuchsia Device Object. 35 url: The url that file to be downloaded from. 36 out_path: Optional. Where to download file to. 37 out_path is /tmp by default. 38 curl_loc: Location of curl binary on fd. 39 remove_file_after_check: Whether to remove the downloaded file after 40 check. 41 timeout: timeout for file download to complete. 42 limit_rate: download rate in bps. None, if do not apply rate limit. 43 additional_args: Any additional args for curl. 44 retry: the retry request times provided in curl command. 45 """ 46 file_directory, file_name = _generate_file_directory_and_file_name( 47 url, out_path) 48 file_path = os.path.join(file_directory, file_name) 49 curl_cmd = curl_loc 50 if limit_rate: 51 curl_cmd += ' --limit-rate %s' % limit_rate 52 if retry: 53 curl_cmd += ' --retry %s' % retry 54 if additional_args: 55 curl_cmd += ' %s' % additional_args 56 curl_cmd += ' --url %s > %s' % (url, file_path) 57 try: 58 fd.log.info( 59 'Download %s to %s by ssh command %s' % (url, file_path, curl_cmd)) 60 61 status = fd.send_command_ssh(curl_cmd, timeout=timeout) 62 if isinstance(status, Error): 63 status = status.result 64 if not status.stderr: 65 if int(status.exit_status) != 0: 66 fd.log.warning('Curl command: "%s" failed with error %s' % 67 (curl_cmd, status.exit_status)) 68 return False 69 70 if _check_file_existence(fd, file_path): 71 fd.log.info( 72 '%s is downloaded to %s successfully' % (url, file_path)) 73 return True 74 else: 75 fd.log.warning('Fail to download %s' % url) 76 return False 77 except Exception as e: 78 fd.log.warning('Download %s failed with exception %s' % (url, e)) 79 return False 80 finally: 81 if remove_file_after_check: 82 fd.log.info('Remove the downloaded file %s' % file_path) 83 fd.send_command_ssh('rm %s' % file_path) 84 85 86def _generate_file_directory_and_file_name(url, out_path): 87 """Splits the file from the url and specifies the appropriate location of 88 where to store the downloaded file. 89 90 Args: 91 url: A url to the file that is going to be downloaded. 92 out_path: The location of where to store the file that is downloaded. 93 94 Returns: 95 file_directory: The directory of where to store the downloaded file. 96 file_name: The name of the file that is being downloaded. 97 """ 98 file_name = url.split('/')[-1] 99 if not out_path: 100 file_directory = '/tmp/' 101 elif not out_path.endswith('/'): 102 file_directory, file_name = os.path.split(out_path) 103 else: 104 file_directory = out_path 105 return file_directory, file_name 106 107 108def _check_file_existence(fd, file_path): 109 """Check file existence by file_path. If expected_file_size 110 is provided, then also check if the file meet the file size requirement. 111 112 Args: 113 fd: A fuchsia device 114 file_path: Where to store the file on the fuchsia device. 115 """ 116 out = fd.send_command_ssh('ls -al "%s"' % file_path) 117 if isinstance(out, Error): 118 out = out.result 119 if 'No such file or directory' in out.stdout: 120 fd.log.debug('File %s does not exist.' % file_path) 121 return False 122 else: 123 fd.log.debug('File %s exists.' % file_path) 124 return True 125