Home | History | Annotate | Download | only in buffet_PrivetSetupFlow
      1 # Copyright 2014 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 time
      7 
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.client.common_lib.cros import avahi_utils
     10 from autotest_lib.client.common_lib.cros.network import interface
     11 from autotest_lib.client.common_lib.cros.network import iw_runner
     12 from autotest_lib.client.common_lib.cros.network import netblock
     13 from autotest_lib.client.common_lib.cros.network import ping_runner
     14 from autotest_lib.client.common_lib.cros.network import xmlrpc_security_types
     15 from autotest_lib.client.common_lib.cros.tendo import peerd_config
     16 from autotest_lib.client.common_lib.cros.tendo import buffet_config
     17 from autotest_lib.client.common_lib.cros.tendo import privet_helper
     18 from autotest_lib.server import site_linux_router
     19 from autotest_lib.server import test
     20 from autotest_lib.server.cros.network import hostap_config
     21 from autotest_lib.server.cros.network import wifi_client
     22 
     23 
     24 PASSPHRASE = 'chromeos'
     25 
     26 PRIVET_AP_STARTUP_TIMEOUT_SECONDS = 30
     27 PRIVET_MDNS_RECORD_TIMEOUT_SECONDS = 10
     28 PRIVET_CONNECT_TIMEOUT_SECONDS = 30
     29 
     30 POLLING_PERIOD = 0.5
     31 
     32 
     33 class buffet_PrivetSetupFlow(test.test):
     34     """This test validates the privet pairing/authentication/setup flow."""
     35     version = 1
     36 
     37     def warmup(self, host, router_hostname=None):
     38         self._router = None
     39         self._shill_xmlrpc_proxy = None
     40         config = buffet_config.BuffetConfig(
     41                 log_verbosity=3,
     42                 enable_ping=True,
     43                 disable_pairing_security=True,
     44                 device_whitelist='any',
     45                 options={'wifi_bootstrap_mode': 'automatic'})
     46         config.restart_with_config(host=host)
     47         self._router = site_linux_router.build_router_proxy(
     48                 test_name=self.__class__.__name__,
     49                 client_hostname=host.hostname,
     50                 router_addr=router_hostname,
     51                 enable_avahi=True)
     52         self._shill_xmlrpc_proxy = wifi_client.get_xmlrpc_proxy(host)
     53         # Cleans up profiles, wifi credentials, sandboxes our new credentials.
     54         self._shill_xmlrpc_proxy.init_test_network_state()
     55         peerd_config.PeerdConfig(verbosity_level=3).restart_with_config(
     56                 host=host)
     57 
     58 
     59     def cleanup(self, host):
     60         if self._shill_xmlrpc_proxy is not None:
     61             self._shill_xmlrpc_proxy.clean_profiles()
     62         if self._router is not None:
     63             self._router.close()
     64         buffet_config.naive_restart(host=host)
     65 
     66 
     67     def run_once(self, host):
     68         helper = privet_helper.PrivetHelper(host=host)
     69         logging.info('Looking for privet bootstrapping network from DUT.')
     70         scan_interface = self._router.get_wlanif(2437, 'managed')
     71         self._router.host.run('%s link set %s up' %
     72                               (self._router.cmd_ip, scan_interface))
     73         start_time = time.time()
     74         privet_bss = None
     75         while time.time() - start_time < PRIVET_AP_STARTUP_TIMEOUT_SECONDS:
     76             bss_list = self._router.iw_runner.scan(scan_interface)
     77             for bss in bss_list or []:
     78                 if helper.is_softap_ssid(bss.ssid):
     79                     privet_bss = bss
     80         if privet_bss is None:
     81             raise error.TestFail('Device did not start soft AP in time.')
     82         self._router.release_interface(scan_interface)
     83 
     84         # Get the netblock of the interface running the AP.
     85         dut_iw_runner = iw_runner.IwRunner(remote_host=host)
     86         devs = dut_iw_runner.list_interfaces(desired_if_type='AP')
     87         if not devs:
     88             raise error.TestFail('No AP devices on DUT?')
     89         ap_interface = interface.Interface(devs[0].if_name, host=host)
     90         ap_netblock = netblock.from_addr(ap_interface.ipv4_address_and_prefix)
     91 
     92         # Set up an AP on the router in the 5Ghz range with WPA2 security.
     93         wpa_config = xmlrpc_security_types.WPAConfig(
     94                 psk=PASSPHRASE,
     95                 wpa_mode=xmlrpc_security_types.WPAConfig.MODE_PURE_WPA2,
     96                 wpa2_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_CCMP])
     97         router_conf = hostap_config.HostapConfig(
     98                 frequency=5240, security_config=wpa_config,
     99                 mode=hostap_config.HostapConfig.MODE_11N_PURE)
    100         self._router.hostap_configure(router_conf)
    101 
    102         # Connect the other interface on the router to the AP on the client
    103         # at a hardcoded IP address.
    104         self._router.configure_managed_station(
    105                 privet_bss.ssid, privet_bss.frequency,
    106                 ap_netblock.get_addr_in_block(200))
    107         station_interface = self._router.get_station_interface(instance=0)
    108         logging.debug('Set up station on %s', station_interface)
    109         self._router.ping(ping_runner.PingConfig(ap_netblock.addr, count=3))
    110 
    111         logging.info('Looking for privet webserver in mDNS records.')
    112         start_time = time.time()
    113         while time.time() - start_time < PRIVET_MDNS_RECORD_TIMEOUT_SECONDS:
    114             all_records = avahi_utils.avahi_browse(host=self._router.host)
    115             records = [record for record in all_records
    116                        if (record.interface == station_interface and
    117                            record.record_type == '_privet._tcp')]
    118             if records:
    119                 break
    120             time.sleep(POLLING_PERIOD)
    121         if not records:
    122             raise error.TestFail('Did not find privet mDNS records in time.')
    123         if len(records) > 1:
    124             raise error.TestFail('Should not see multiple privet records.')
    125         privet_record = records[0]
    126         # TODO(wiley) pull the HTTPs port number out of the /info API.
    127         helper = privet_helper.PrivetdHelper(
    128                 host=self._router.host,
    129                 hostname=privet_record.address,
    130                 http_port=int(privet_record.port))
    131         helper.ping_server()
    132 
    133         # Now configure the client with WiFi credentials.
    134         auth_token = helper.privet_auth()
    135         ssid = self._router.get_ssid()
    136         data = helper.setup_add_wifi_credentials(ssid, PASSPHRASE)
    137         helper.setup_start(data, auth_token)
    138 
    139         logging.info('Waiting for DUT to connect to router network.')
    140         start_time = time.time()
    141         # Wait for the DUT to take down the AP.
    142         while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
    143             if not dut_iw_runner.list_interfaces(desired_if_type='AP'):
    144                 break
    145             time.sleep(POLLING_PERIOD)
    146         else:
    147             raise error.TestFail('Timeout waiting for DUT to take down AP.')
    148 
    149         # But we should be able to ping the client from the router's AP.
    150         while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
    151             if dut_iw_runner.list_interfaces(desired_if_type='managed'):
    152                 break
    153             time.sleep(POLLING_PERIOD)
    154         else:
    155             raise error.TestFail('Timeout waiting for DUT managerd interface.')
    156 
    157         while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
    158             devs = dut_iw_runner.list_interfaces(desired_if_type='managed')
    159             if devs:
    160                 managed_interface = interface.Interface(devs[0].if_name,
    161                                                         host=host)
    162                 # Check if we have an IP yet.
    163                 if managed_interface.ipv4_address_and_prefix:
    164                     break
    165             time.sleep(POLLING_PERIOD)
    166         else:
    167             raise error.TestFail('Timeout waiting for DUT managerd interface.')
    168 
    169         managed_netblock = netblock.from_addr(
    170                 managed_interface.ipv4_address_and_prefix)
    171         while time.time() - start_time < PRIVET_CONNECT_TIMEOUT_SECONDS:
    172             PING_COUNT = 3
    173             result = self._router.ping(
    174                     ping_runner.PingConfig(managed_netblock.addr,
    175                                            ignore_result=True,
    176                                            count=PING_COUNT))
    177             if result.received == PING_COUNT:
    178                 break
    179             time.sleep(POLLING_PERIOD)
    180         else:
    181             raise error.TestFail('Timeout before ping was successful.')
    182 
    183         # And buffet should think it is online as well.
    184         helper = privet_helper.PrivetdHelper(
    185                 host=host, hostname=managed_netblock.addr,
    186                 http_port=int(privet_record.port))
    187         helper.ping_server()
    188         if not helper.wifi_setup_was_successful(ssid, auth_token):
    189             raise error.TestFail('Device claims to be offline, but is online.')
    190