Paul Stewart | 98d75b6 | 2011-04-01 15:04:27 -0700 | [diff] [blame] | 1 | # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | import re, socket, subprocess |
| 6 | from autotest_lib.client.common_lib import error |
| 7 | |
| 8 | class HostRoute(object): |
| 9 | """ |
| 10 | Host Route: A utility for retrieving information about our route to a host |
| 11 | |
| 12 | """ |
| 13 | |
| 14 | def __init__(self, host): |
| 15 | self.host = host # Remote host |
| 16 | self.calculate() |
| 17 | |
| 18 | def calculate(self): |
| 19 | output = self.run_command(["ip", "route", "get", self.host]) |
| 20 | # This converts "172.22.18.53 via 10.0.0.1 dev eth0 src 10.0.0.200 \n.." |
| 21 | # into ("via", "10.0.0.1", "dev", "eth0", "src", "10.0.0.200") |
| 22 | route_info = re.split("\s*", output.split("\n")[0].rstrip(' '))[1:] |
| 23 | |
| 24 | # Further, convert the list into a dict {"via": "10.0.0.1", ...} |
| 25 | self.route_info = dict(tuple(route_info[i:i+2]) |
| 26 | for i in range(0, len(route_info), 2)) |
| 27 | |
| 28 | if 'src' not in self.route_info: |
| 29 | raise error.TestFail('Cannot find route to host %s' % self.host) |
| 30 | |
| 31 | class LocalHostRoute(HostRoute): |
| 32 | """ |
| 33 | Self Host Route: Retrieve host route for the test-host machine |
| 34 | |
| 35 | """ |
| 36 | def __init__(self, host): |
| 37 | # TODO(pstew): If we could depend on the host having the "ip" command |
| 38 | # we would just be able to do this: |
| 39 | # |
| 40 | # HostRoute.__init__(self, host) |
| 41 | # |
| 42 | # but alas, we can't depend on this, so we fake it by creating a |
| 43 | # socket and figuring out what local address we bound to if we |
| 44 | # connected to the client |
| 45 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
| 46 | sock.connect((host, 22)) # NB: Port doesn't matter |
| 47 | self.route_info = { 'src': sock.getsockname()[0] } |
| 48 | |
| 49 | def run_command(self, args): |
| 50 | return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0] |
| 51 | |
| 52 | class RemoteHostRoute(HostRoute): |
| 53 | """ |
| 54 | Remote Host Route: Retrieve host route for a remote (DUT, server) machine |
| 55 | |
| 56 | """ |
| 57 | def __init__(self, remote, host): |
| 58 | self.remote = remote |
| 59 | HostRoute.__init__(self, host) |
| 60 | |
| 61 | def run_command(self, args): |
| 62 | return self.remote.run(' '.join(args)).stdout |