Home | History | Annotate | Download | only in chaos_lib
      1 # Copyright 2016 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 contextlib
      6 import datetime
      7 import logging
      8 import pprint
      9 import time
     10 
     11 import common
     12 from autotest_lib.client.common_lib import error
     13 from autotest_lib.client.common_lib.cros.network import ap_constants
     14 from autotest_lib.client.common_lib.cros.network import iw_runner
     15 from autotest_lib.server import hosts
     16 from autotest_lib.server import site_linux_system
     17 from autotest_lib.server.cros import host_lock_manager
     18 from autotest_lib.server.cros.ap_configurators import ap_batch_locker
     19 from autotest_lib.server.cros.ap_configurators \
     20         import ap_configurator_factory
     21 from autotest_lib.server.cros.network import chaos_clique_utils as utils
     22 from autotest_lib.server.cros.network import wifi_client
     23 from autotest_lib.server.hosts import adb_host
     24 
     25 
     26 class StaticRunner(object):
     27     """Object to run a network_WiFi_ChaosXXX test."""
     28 
     29 
     30     def __init__(self, test, host, spec):
     31         """Initializes and runs test.
     32 
     33         @param test: a string, test name.
     34         @param host: an Autotest host object, device under test.
     35         @param spec: an APSpec object.
     36 
     37         """
     38         self._test = test
     39         self._host = host
     40         self._ap_spec = spec
     41         # Log server and DUT times
     42         dt = datetime.datetime.now()
     43         logging.info('Server time: %s', dt.strftime('%a %b %d %H:%M:%S %Y'))
     44         logging.info('DUT time: %s', self._host.run('date').stdout.strip())
     45 
     46 
     47     def run(self, job, batch_size=10, tries=10, capturer_hostname=None,
     48             conn_worker=None, work_client_hostname=None,
     49             disabled_sysinfo=False):
     50         """Executes Chaos test.
     51 
     52         @param job: an Autotest job object.
     53         @param batch_size: an integer, max number of APs to lock in one batch.
     54         @param tries: an integer, number of iterations to run per AP.
     55         @param capturer_hostname: a string or None, hostname or IP of capturer.
     56         @param conn_worker: ConnectionWorkerAbstract or None, to run extra
     57                             work after successful connection.
     58         @param work_client_hostname: a string or None, hostname of work client
     59         @param disabled_sysinfo: a bool, disable collection of logs from DUT.
     60 
     61 
     62         @raises TestError: Packet capture DUT may be down or another test may be
     63                            running in the chamber.
     64         """
     65 
     66         lock_manager = host_lock_manager.HostLockManager()
     67         host_prefix = self._host.hostname.split('-')[0]
     68         if ap_constants.CASEY5 in host_prefix:
     69             test_type = ap_constants.AP_TEST_TYPE_CASEY5
     70         elif ap_constants.CASEY7 in host_prefix:
     71             test_type = ap_constants.AP_TEST_TYPE_CASEY7
     72         else:
     73             test_type = None
     74 
     75         with host_lock_manager.HostsLockedBy(lock_manager):
     76             capture_host = utils.allocate_packet_capturer(
     77                     lock_manager, hostname=capturer_hostname,
     78                     prefix=host_prefix)
     79             # Cleanup and reboot packet capturer before the test.
     80             utils.sanitize_client(capture_host)
     81             capturer = site_linux_system.LinuxSystem(capture_host, {},
     82                                                      'packet_capturer')
     83 
     84             # Run iw scan and abort if more than allowed number of APs are up.
     85             iw_command = iw_runner.IwRunner(capture_host)
     86             start_time = time.time()
     87             logging.info('Performing a scan with a max timeout of 30 seconds.')
     88             capture_interface = 'wlan0'
     89             capturer_info = capture_host.run('cat /etc/lsb-release',
     90                                          ignore_status=True, timeout=5).stdout
     91             if 'whirlwind' in capturer_info:
     92                 # Use the dual band aux radio for scanning networks.
     93                 capture_interface = 'wlan2'
     94             while time.time() - start_time <= ap_constants.MAX_SCAN_TIMEOUT:
     95                 networks = iw_command.scan(capture_interface)
     96                 if networks is None:
     97                     if (time.time() - start_time ==
     98                             ap_constants.MAX_SCAN_TIMEOUT):
     99                         raise error.TestError(
    100                             'Packet capturer is not responding to scans. Check'
    101                             'device and re-run test')
    102                     continue
    103                 elif len(networks) < ap_constants.MAX_SSID_COUNT:
    104                     break
    105                 elif len(networks) >= ap_constants.MAX_SSID_COUNT:
    106                     raise error.TestError(
    107                         'Probably someone is already running a '
    108                         'chaos test?!')
    109 
    110             if conn_worker is not None:
    111                 work_client_machine = utils.allocate_packet_capturer(
    112                         lock_manager, hostname=work_client_hostname)
    113                 conn_worker.prepare_work_client(work_client_machine)
    114 
    115             batch_locker = ap_batch_locker.ApBatchLocker(
    116                     lock_manager, self._ap_spec,
    117                     ap_test_type=test_type)
    118 
    119             while batch_locker.has_more_aps():
    120                 # Work around for CrOS devices only:crbug.com/358716
    121                 # Do not reboot Android devices:b/27977927
    122                 if self._host.get_os_type() != adb_host.OS_TYPE_ANDROID:
    123                     utils.sanitize_client(self._host)
    124                 healthy_dut = True
    125 
    126                 with contextlib.closing(wifi_client.WiFiClient(
    127                     hosts.create_host({'hostname' : self._host.hostname,
    128                             'afe_host' : self._host._afe_host},
    129                             host_class=self._host.__class__),
    130                     './debug', False)) as client:
    131 
    132                     aps = batch_locker.get_ap_batch(batch_size=batch_size)
    133                     if not aps:
    134                         logging.info('No more APs to test.')
    135                         break
    136 
    137                     utils.configure_aps(aps, self._ap_spec)
    138 
    139                     aps = utils.filter_quarantined_and_config_failed_aps(aps,
    140                             batch_locker, job)
    141 
    142                     for ap in aps:
    143                         # http://crbug.com/306687
    144                         if ap.ssid == None:
    145                             logging.error('The SSID was not set for the AP:%s',
    146                                           ap)
    147 
    148                         healthy_dut = utils.is_dut_healthy(client, ap)
    149 
    150                         if not healthy_dut:
    151                             logging.error('DUT is not healthy, rebooting.')
    152                             batch_locker.unlock_and_reclaim_aps()
    153                             break
    154 
    155                         networks = utils.return_available_networks(
    156                                 ap, capturer, job, self._ap_spec)
    157 
    158                         if networks is None:
    159                             # If scan returned no networks, iw scan failed.
    160                             # Reboot the packet capturer device and
    161                             # reconfigure the capturer.
    162                             batch_locker.unlock_and_reclaim_ap(ap.host_name)
    163                             logging.error('Packet capture is not healthy, '
    164                                           'rebooting.')
    165                             capturer.host.reboot()
    166                             capturer = site_linux_system.LinuxSystem(
    167                                            capture_host, {},'packet_capturer')
    168                             continue
    169                         if networks == list():
    170                             # Packet capturer did not find the SSID in scan or
    171                             # there was a security mismatch.
    172                             utils.release_ap(ap, batch_locker)
    173                             continue
    174 
    175                         assoc_params = ap.get_association_parameters()
    176 
    177                         if not utils.is_conn_worker_healthy(
    178                                 conn_worker, ap, assoc_params, job):
    179                             utils.release_ap(
    180                                     ap, batch_locker)
    181                             continue
    182 
    183                         name = ap.name
    184                         kernel_ver = self._host.get_kernel_ver()
    185                         firmware_ver = utils.get_firmware_ver(self._host)
    186                         if not firmware_ver:
    187                             firmware_ver = "Unknown"
    188 
    189                         debug_dict = {'+++PARSE DATA+++': '+++PARSE DATA+++',
    190                                       'SSID': ap._ssid,
    191                                       'DUT': client.wifi_mac,
    192                                       'AP Info': ap.name,
    193                                       'kernel_version': kernel_ver,
    194                                       'wifi_firmware_version': firmware_ver}
    195                         debug_string = pprint.pformat(debug_dict)
    196 
    197                         logging.info('Waiting %d seconds for the AP dhcp '
    198                                      'server', ap.dhcp_delay)
    199                         time.sleep(ap.dhcp_delay)
    200 
    201                         result = job.run_test(self._test,
    202                                      capturer=capturer,
    203                                      capturer_frequency=networks[0].frequency,
    204                                      capturer_ht_type=networks[0].ht,
    205                                      host=self._host,
    206                                      assoc_params=assoc_params,
    207                                      client=client,
    208                                      tries=tries,
    209                                      debug_info=debug_string,
    210                                      # Copy all logs from the system
    211                                      disabled_sysinfo=disabled_sysinfo,
    212                                      conn_worker=conn_worker,
    213                                      tag=ap.ssid if conn_worker is None else
    214                                          '%s.%s' % (conn_worker.name, ap.ssid))
    215 
    216                         utils.release_ap(ap, batch_locker)
    217 
    218                         if conn_worker is not None:
    219                             conn_worker.cleanup()
    220 
    221                     if not healthy_dut:
    222                         continue
    223 
    224                 batch_locker.unlock_aps()
    225 
    226             capturer.close()
    227 
    228             factory = ap_configurator_factory.APConfiguratorFactory(
    229                     test_type)
    230             factory.turn_off_all_routers([])
    231