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