1*9c5db199SXin Li# Lint as: python2, python3 2*9c5db199SXin Li# Copyright (c) 2019 The Chromium OS Authors. All rights reserved. 3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 4*9c5db199SXin Li# found in the LICENSE file. 5*9c5db199SXin Li 6*9c5db199SXin Liimport logging 7*9c5db199SXin Lifrom six.moves import urllib 8*9c5db199SXin Liimport socket 9*9c5db199SXin Liimport time 10*9c5db199SXin Li 11*9c5db199SXin Lifrom autotest_lib.client.bin import utils 12*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 13*9c5db199SXin Li 14*9c5db199SXin Li 15*9c5db199SXin Lidef CheckThatInterfaceCanAccessDestination(host, 16*9c5db199SXin Li interface, 17*9c5db199SXin Li families=[socket.AF_UNSPEC]): 18*9c5db199SXin Li """ 19*9c5db199SXin Li Checks that we can access a host using a specific interface. 20*9c5db199SXin Li 21*9c5db199SXin Li @param host: Destination host 22*9c5db199SXin Li @param interface: Name of the network interface to be used 23*9c5db199SXin Li @raises: error.TestFail if the interface cannot access the specified host. 24*9c5db199SXin Li 25*9c5db199SXin Li """ 26*9c5db199SXin Li logging.debug('Check connection to %s', host) 27*9c5db199SXin Li # addrinfo records: (family, type, proto, canonname, (addr, port)) 28*9c5db199SXin Li server_addresses = [] 29*9c5db199SXin Li for family in families: 30*9c5db199SXin Li try: 31*9c5db199SXin Li records = socket.getaddrinfo(host, 80, family) 32*9c5db199SXin Li except: 33*9c5db199SXin Li # Just ignore this family. 34*9c5db199SXin Li continue 35*9c5db199SXin Li server_addresses.extend(record[4][0] for record in records) 36*9c5db199SXin Li 37*9c5db199SXin Li found_route = False 38*9c5db199SXin Li failing_addresses = [] 39*9c5db199SXin Li for address in set(server_addresses): 40*9c5db199SXin Li # Routes may not always be up by this point. Note that routes for v4 or 41*9c5db199SXin Li # v6 may come up before the other, so we simply do this poll for all 42*9c5db199SXin Li # addresses. 43*9c5db199SXin Li try: 44*9c5db199SXin Li utils.poll_for_condition(condition=lambda: utils.ping( 45*9c5db199SXin Li address, interface=interface, tries=2, timeout=3) == 0, 46*9c5db199SXin Li exception=Exception('No route to %s' % 47*9c5db199SXin Li address), 48*9c5db199SXin Li timeout=2) 49*9c5db199SXin Li except Exception as e: 50*9c5db199SXin Li logging.info(e) 51*9c5db199SXin Li failing_addresses.append(address) 52*9c5db199SXin Li else: 53*9c5db199SXin Li found_route = True 54*9c5db199SXin Li 55*9c5db199SXin Li if not found_route: 56*9c5db199SXin Li raise error.TestFail('Interface %s cannot connect to %s' % (interface, 57*9c5db199SXin Li failing_addresses)) 58*9c5db199SXin Li 59*9c5db199SXin Li 60*9c5db199SXin LiFETCH_URL_PATTERN_FOR_TEST = \ 61*9c5db199SXin Li 'http://testing-chargen.appspot.com/download?size=%d' 62*9c5db199SXin Li 63*9c5db199SXin Lidef FetchUrl(url_pattern, bytes_to_fetch=10, fetch_timeout=10): 64*9c5db199SXin Li """ 65*9c5db199SXin Li Fetches a specified number of bytes from a URL. 66*9c5db199SXin Li 67*9c5db199SXin Li @param url_pattern: URL pattern for fetching a specified number of bytes. 68*9c5db199SXin Li %d in the pattern is to be filled in with the number of bytes to 69*9c5db199SXin Li fetch. 70*9c5db199SXin Li @param bytes_to_fetch: Number of bytes to fetch. 71*9c5db199SXin Li @param fetch_timeout: Number of seconds to wait for the fetch to complete 72*9c5db199SXin Li before it times out. 73*9c5db199SXin Li @return: The time in seconds spent for fetching the specified number of 74*9c5db199SXin Li bytes. 75*9c5db199SXin Li @raises: error.TestError if one of the following happens: 76*9c5db199SXin Li - The fetch takes no time. 77*9c5db199SXin Li - The number of bytes fetched differs from the specified 78*9c5db199SXin Li number. 79*9c5db199SXin Li 80*9c5db199SXin Li """ 81*9c5db199SXin Li # Limit the amount of bytes to read at a time. 82*9c5db199SXin Li _MAX_FETCH_READ_BYTES = 1024 * 1024 83*9c5db199SXin Li 84*9c5db199SXin Li url = url_pattern % bytes_to_fetch 85*9c5db199SXin Li logging.info('FetchUrl %s', url) 86*9c5db199SXin Li start_time = time.time() 87*9c5db199SXin Li result = urllib.request.urlopen(url, timeout=fetch_timeout) 88*9c5db199SXin Li bytes_fetched = 0 89*9c5db199SXin Li while bytes_fetched < bytes_to_fetch: 90*9c5db199SXin Li bytes_left = bytes_to_fetch - bytes_fetched 91*9c5db199SXin Li bytes_to_read = min(bytes_left, _MAX_FETCH_READ_BYTES) 92*9c5db199SXin Li bytes_read = len(result.read(bytes_to_read)) 93*9c5db199SXin Li bytes_fetched += bytes_read 94*9c5db199SXin Li if bytes_read != bytes_to_read: 95*9c5db199SXin Li raise error.TestError('FetchUrl tried to read %d bytes, but got ' 96*9c5db199SXin Li '%d bytes instead.' % 97*9c5db199SXin Li (bytes_to_read, bytes_read)) 98*9c5db199SXin Li fetch_time = time.time() - start_time 99*9c5db199SXin Li if fetch_time > fetch_timeout: 100*9c5db199SXin Li raise error.TestError('FetchUrl exceeded timeout.') 101*9c5db199SXin Li 102*9c5db199SXin Li return fetch_time 103