Home | History | Annotate | Download | only in cros
      1 # Copyright (c) 2013 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 logging
      6 import os
      7 import shutil
      8 
      9 from autotest_lib.client.common_lib import error, utils
     10 from autotest_lib.client.common_lib.cros import avahi_utils
     11 from autotest_lib.client.cros import service_stopper, tcpdump
     12 
     13 
     14 P2P_SHARE_PATH = '/var/cache/p2p'
     15 
     16 # A path used to store the existing p2p files during the test and restore them
     17 # once the test finishes.
     18 P2P_SHARE_BACKUP_PATH = '/var/cache/p2p-backup'
     19 
     20 
     21 def p2p_backup_files(backup_path=P2P_SHARE_BACKUP_PATH):
     22     """Backup the P2P shared files and create an empty shared directory.
     23 
     24     p2p-server shall not be running during backup or restore.
     25 
     26     @param backup_path: The path where the files will be moved to.
     27     @raise error.TestError
     28     """
     29     try:
     30         if os.path.exists(backup_path):
     31             shutil.rmtree(backup_path)
     32         if os.path.exists(P2P_SHARE_PATH):
     33             os.rename(P2P_SHARE_PATH, backup_path)
     34     except OSError, e:
     35         raise error.TestError("Error on P2P files backup: %s" % (e.message))
     36 
     37 
     38 def p2p_restore_files(backup_path=P2P_SHARE_BACKUP_PATH):
     39     """Restore the P2P shared files from a backup and *delete* the backup.
     40 
     41     p2p-server shall not be running during backup or restore.
     42 
     43     @param backup_path: The path where the files will be moved from.
     44     """
     45     if os.path.exists(P2P_SHARE_PATH):
     46         shutil.rmtree(P2P_SHARE_PATH, ignore_errors=True)
     47     if os.path.exists(backup_path):
     48         os.rename(backup_path, P2P_SHARE_PATH)
     49 
     50 
     51 class P2PServerOverTap(object):
     52     """Manage a p2p-server instance running over a TAP interface.
     53 
     54     This class manages a p2p-server instance configured to run over a TAP
     55     interface, useful for any test that needs to interact with the p2p-server
     56     (and its p2p-http-server instance) on a controled network environment.
     57     """
     58     def __init__(self, tap_ip='169.254.10.1', tap_mask=24, tap_name='faketap'):
     59         """Initialize the configuration.
     60 
     61         @param tap_ip: IPv4 address for the TAP interface on the DUT's end.
     62         @param tap_mask: Network mask fot the tap_ip address.
     63         @param tap_name: The name prefix for the TAP interface.
     64         """
     65         # The network 169.254/16 shouldn't clash with other real services and we
     66         # use a /24 subnet of it as the default safe value here.
     67         self._tap_ip = tap_ip
     68         self._tap_mask = tap_mask
     69         self._tap_name = tap_name
     70         self._services = None
     71         self.tap = None
     72         self._tcpdump = None
     73 
     74 
     75     def setup(self, dumpdir=None):
     76         """Initializes avahi daemon on a new tap interface.
     77 
     78         @param dumpdir: Directory where the traffic on the new tap interface
     79                         is recorded. A value of None disables traffic dumping.
     80         """
     81         try:
     82             from lansim import tuntap
     83         except ImportError:
     84             logging.exception('Failed to import lansim.')
     85             raise error.TestError('Error importing lansim. Did you setup_dep '
     86                                   'and install_pkg lansim on your test?')
     87 
     88         # Ensure p2p and avahi aren't running.
     89         self._services = service_stopper.ServiceStopper(['p2p', 'avahi'])
     90         self._services.stop_services()
     91 
     92         # Backup p2p files.
     93         p2p_backup_files()
     94 
     95         # Initialize the TAP interface.
     96         self.tap = tuntap.TunTap(tuntap.IFF_TAP, name=self._tap_name)
     97         self.tap.set_addr(self._tap_ip, self._tap_mask)
     98         self.tap.up()
     99 
    100         # Enable traffic dump.
    101         if not dumpdir is None:
    102             dumpfile = os.path.join(dumpdir, 'dump-%s.pcap' % self.tap.name)
    103             self._tcpdump = tcpdump.Tcpdump(self.tap.name, dumpfile)
    104 
    105         # Re-launch avahi-daemon on the TAP interface only.
    106         avahi_utils.avahi_start_on_iface(self.tap.name)
    107         utils.system("start p2p")
    108 
    109 
    110     def cleanup(self):
    111         """Restore the original environment as before the call to setup().
    112 
    113         This method makes a best-effort attempt to restore the environment and
    114         logs all the errors encountered but doesn't fail.
    115         """
    116         try:
    117             utils.system('stop p2p')
    118             avahi_utils.avahi_stop()
    119         except:
    120             logging.exception('Failed to stop tested services.')
    121 
    122         if self._tcpdump:
    123             self._tcpdump.stop()
    124 
    125         if self.tap:
    126             self.tap.down()
    127 
    128         # Restore p2p files.
    129         try:
    130             p2p_restore_files()
    131         except OSError:
    132             logging.exception('Failed to restore the P2P backup.')
    133 
    134         if self._services:
    135             self._services.restore_services()
    136