Home | History | Annotate | Download | only in server
      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
     63