blob: 3c780d46ef593fd65f3b21647708d8593aaf7052 [file] [log] [blame]
Derek Beckett8affba02020-10-20 14:24:18 -07001# Lint as: python2, python3
Alex Khouderchah7d763ab2019-07-25 12:22:20 -07002# Copyright (c) 2019 The Chromium OS Authors. All rights reserved.
David Rochberg1068c202011-05-18 15:42:03 -04003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Ben Chan89216c62013-05-07 15:55:15 -07006import logging
Derek Beckett8affba02020-10-20 14:24:18 -07007from six.moves import urllib
Ben Chan89216c62013-05-07 15:55:15 -07008import socket
9import time
David Rochberg65a34fc2011-12-29 17:39:13 -050010
Alex Khouderchah7d763ab2019-07-25 12:22:20 -070011from autotest_lib.client.bin import utils
Ben Chan89216c62013-05-07 15:55:15 -070012from autotest_lib.client.common_lib import error
David Rochbergc1b32402011-05-24 16:51:48 -040013
David Rochberg6eef6cc2011-10-31 10:19:06 -040014
Andrew Lassalle56a2a992021-06-04 16:34:17 -070015def CheckThatInterfaceCanAccessDestination(host,
16 interface,
17 families=[socket.AF_UNSPEC]):
Thieu Le0f2a00d2013-05-30 13:43:55 -070018 """
Andrew Lassalle56a2a992021-06-04 16:34:17 -070019 Checks that we can access a host using a specific interface.
Ben Chan89216c62013-05-07 15:55:15 -070020
Thieu Le0f2a00d2013-05-30 13:43:55 -070021 @param host: Destination host
Andrew Lassalle56a2a992021-06-04 16:34:17 -070022 @param interface: Name of the network interface to be used
23 @raises: error.TestFail if the interface cannot access the specified host.
Ben Chan89216c62013-05-07 15:55:15 -070024
25 """
Andrew Lassalle56a2a992021-06-04 16:34:17 -070026 logging.debug('Check connection to %s', host)
Alex Khouderchah7d763ab2019-07-25 12:22:20 -070027 # addrinfo records: (family, type, proto, canonname, (addr, port))
Eric Carusocd26f142021-06-01 11:57:32 -070028 server_addresses = []
29 for family in families:
30 try:
31 records = socket.getaddrinfo(host, 80, family)
32 except:
33 # Just ignore this family.
34 continue
35 server_addresses.extend(record[4][0] for record in records)
36
Eric Carusofbd70812021-01-20 07:21:39 -080037 found_route = False
38 failing_addresses = []
Andrew Lassalle56a2a992021-06-04 16:34:17 -070039 for address in set(server_addresses):
Alex Khouderchah7d763ab2019-07-25 12:22:20 -070040 # Routes may not always be up by this point. Note that routes for v4 or
41 # v6 may come up before the other, so we simply do this poll for all
42 # addresses.
Eric Carusofbd70812021-01-20 07:21:39 -080043 try:
Andrew Lassalle56a2a992021-06-04 16:34:17 -070044 utils.poll_for_condition(condition=lambda: utils.ping(
45 address, interface=interface, tries=2, timeout=2) == 0,
46 exception=Exception('No route to %s' %
47 address),
48 timeout=2)
Eric Carusofbd70812021-01-20 07:21:39 -080049 except Exception as e:
50 logging.info(e)
51 failing_addresses.append(address)
52 else:
53 found_route = True
54
55 if not found_route:
Eric Caruso252879e2021-06-17 08:07:59 -070056 raise error.TestFail('Interface %s cannot connect to %s' % (interface,
57 failing_addresses))
Andrew Lassalle56a2a992021-06-04 16:34:17 -070058
Ben Chan89216c62013-05-07 15:55:15 -070059
60FETCH_URL_PATTERN_FOR_TEST = \
61 'http://testing-chargen.appspot.com/download?size=%d'
62
63def FetchUrl(url_pattern, bytes_to_fetch=10, fetch_timeout=10):
Thieu Le0f2a00d2013-05-30 13:43:55 -070064 """
65 Fetches a specified number of bytes from a URL.
Ben Chan89216c62013-05-07 15:55:15 -070066
Thieu Le0f2a00d2013-05-30 13:43:55 -070067 @param url_pattern: URL pattern for fetching a specified number of bytes.
Ben Chan89216c62013-05-07 15:55:15 -070068 %d in the pattern is to be filled in with the number of bytes to
69 fetch.
Thieu Le0f2a00d2013-05-30 13:43:55 -070070 @param bytes_to_fetch: Number of bytes to fetch.
71 @param fetch_timeout: Number of seconds to wait for the fetch to complete
Ben Chan89216c62013-05-07 15:55:15 -070072 before it times out.
Thieu Le0f2a00d2013-05-30 13:43:55 -070073 @return: The time in seconds spent for fetching the specified number of
74 bytes.
75 @raises: error.TestError if one of the following happens:
Ben Chan89216c62013-05-07 15:55:15 -070076 - The fetch takes no time.
Thieu Le0f2a00d2013-05-30 13:43:55 -070077 - The number of bytes fetched differs from the specified
78 number.
Ben Chan89216c62013-05-07 15:55:15 -070079
80 """
Thieu Le6369a1d2014-04-23 14:31:36 -070081 # Limit the amount of bytes to read at a time.
82 _MAX_FETCH_READ_BYTES = 1024 * 1024
83
Ben Chan89216c62013-05-07 15:55:15 -070084 url = url_pattern % bytes_to_fetch
85 logging.info('FetchUrl %s', url)
86 start_time = time.time()
Derek Beckett8affba02020-10-20 14:24:18 -070087 result = urllib.request.urlopen(url, timeout=fetch_timeout)
Thieu Le6369a1d2014-04-23 14:31:36 -070088 bytes_fetched = 0
89 while bytes_fetched < bytes_to_fetch:
90 bytes_left = bytes_to_fetch - bytes_fetched
91 bytes_to_read = min(bytes_left, _MAX_FETCH_READ_BYTES)
92 bytes_read = len(result.read(bytes_to_read))
93 bytes_fetched += bytes_read
94 if bytes_read != bytes_to_read:
95 raise error.TestError('FetchUrl tried to read %d bytes, but got '
96 '%d bytes instead.' %
97 (bytes_to_read, bytes_read))
98 fetch_time = time.time() - start_time
99 if fetch_time > fetch_timeout:
100 raise error.TestError('FetchUrl exceeded timeout.')
Ben Chan89216c62013-05-07 15:55:15 -0700101
102 return fetch_time