Home | History | Annotate | Download | only in cros
      1 # Copyright (c) 2012 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 ConfigParser
      6 import logging
      7 import os
      8 import time
      9 
     10 from autotest_lib.client.common_lib.cros.network import ap_constants
     11 from autotest_lib.site_utils.rpm_control_system import rpm_client
     12 from autotest_lib.server.cros.ap_configurators import ap_spec
     13 
     14 # chaos_shadow_ap_list.conf is used for testing against local APs.
     15 AP_CONFIG_FILES = { ap_constants.AP_TEST_TYPE_CHAOS:
     16                     ('chaos_ap_list.conf',
     17                      'chaos_shadow_ap_list.conf'),}
     18 
     19 TIMEOUT = 100
     20 
     21 def get_ap_list(ap_test_type):
     22     """
     23     Returns the list of AP's from the corresponding configuration file.
     24 
     25     @param ap_test_type: Used to determine which type of test we're
     26                          currently running (Chaos vs Clique).
     27     @returns a list of AP objects.
     28 
     29     """
     30     aps = []
     31     ap_config_files = AP_CONFIG_FILES.get(ap_test_type, None)
     32     for filename in ap_config_files:
     33         ap_config = ConfigParser.RawConfigParser(
     34                 {AP.CONF_RPM_MANAGED: 'False'})
     35         path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
     36                             filename)
     37         if not os.path.exists(path):
     38             logging.warning('Skipping missing config: "%s"', path)
     39             continue
     40 
     41         logging.debug('Reading config from: "%s"', path)
     42         ap_config.read(path)
     43         for bss in ap_config.sections():
     44             aps.append(AP(bss, ap_config))
     45     return aps
     46 
     47 
     48 class APPowerException(Exception):
     49     """ Exception raised when AP fails to power on. """
     50     pass
     51 
     52 class APSectionError(Exception):
     53     """ Exception raised when AP instance does not exist in the config. """
     54     pass
     55 
     56 class AP(object):
     57     """ An instance of an ap defined in the chaos config file.
     58 
     59     This object is a wrapper that can be used to retrieve information
     60     about an AP in the chaos lab, and control its power.
     61 
     62     """
     63 
     64 
     65     # Keys used in the config file.
     66     CONF_SSID = 'ssid'
     67     CONF_BRAND = 'brand'
     68     CONF_MODEL = 'model'
     69     CONF_WAN_MAC = 'wan mac'
     70     CONF_WAN_HOST = 'wan_hostname'
     71     CONF_RPM_MANAGED = 'rpm_managed'
     72     CONF_BSS = 'bss'
     73     CONF_BSS5 = 'bss5'
     74     CONF_BANDWIDTH = 'bandwidth'
     75     CONF_SECURITY = 'security'
     76     CONF_PSK = 'psk'
     77     CONF_FREQUENCY = 'frequency'
     78     CONF_BAND = 'band'
     79     CONF_CHANNEL = 'channel'
     80     CONF_CLASS = 'class_name'
     81     CONF_ADMIN = 'admin_url'
     82     CONF_ADMIN_IP = 'admin_ip'
     83 
     84 
     85     def __init__(self, bss, config):
     86         """
     87         Intialize object
     88 
     89         @param bss: string containing bssid
     90         @param config: ConfigParser read from file
     91 
     92         """
     93         if not config.has_section(bss):
     94             raise APSectionError('BSS (%s) not defined.' % bss)
     95         self.bss = bss
     96         self.ap_config = config
     97 
     98 
     99     def get_ssid(self):
    100         """@return string ssid for AP from config file"""
    101         return self.ap_config.get(self.bss, self.CONF_SSID)
    102 
    103 
    104     def get_brand(self):
    105         """@return string brand for AP from config file"""
    106         return self.ap_config.get(self.bss, self.CONF_BRAND)
    107 
    108 
    109     def get_model(self):
    110         """@return string model for AP from config file"""
    111         return self.ap_config.get(self.bss, self.CONF_MODEL)
    112 
    113 
    114     def get_wan_mac(self):
    115         """@return string mac for WAN port of AP from config file"""
    116         return self.ap_config.get(self.bss, self.CONF_WAN_MAC)
    117 
    118 
    119     def get_wan_host(self):
    120         """@return string host for AP from config file"""
    121         return self.ap_config.get(self.bss, self.CONF_WAN_HOST)
    122 
    123 
    124     def get_rpm_managed(self):
    125         """@return bool for AP power via rpm from config file"""
    126         return self.ap_config.getboolean(self.bss, self.CONF_RPM_MANAGED)
    127 
    128 
    129     def get_bss(self):
    130         """@return string bss for AP from config file"""
    131         try:
    132             bss = self.ap_config.get(self.bss, self.CONF_BSS)
    133         except ConfigParser.NoOptionError as e:
    134             bss = 'N/A'
    135         return bss
    136 
    137 
    138     def get_bss5(self):
    139         """@return string bss5 for AP from config file"""
    140         try:
    141             bss5 = self.ap_config.get(self.bss, self.CONF_BSS5)
    142         except ConfigParser.NoOptionError as e:
    143             bss5 = 'N/A'
    144         return bss5
    145 
    146     def get_bandwidth(self):
    147         """@return string bandwidth for AP from config file"""
    148         return self.ap_config.get(self.bss, self.CONF_BANDWIDTH)
    149 
    150 
    151     def get_security(self):
    152         """@return string security for AP from config file"""
    153         return self.ap_config.get(self.bss, self.CONF_SECURITY)
    154 
    155 
    156     def get_psk(self):
    157         """@return string psk for AP from config file"""
    158         return self.ap_config.get(self.bss, self.CONF_PSK)
    159 
    160 
    161     def get_frequency(self):
    162         """@return int frequency for AP from config file"""
    163         return int(self.ap_config.get(self.bss, self.CONF_FREQUENCY))
    164 
    165     def get_channel(self):
    166         """@return int channel for AP from config file"""
    167         return ap_spec.CHANNEL_TABLE[self.get_frequency()]
    168 
    169 
    170     def get_band(self):
    171         """@return string band for AP from config file"""
    172         if self.get_frequency() < 4915:
    173             return ap_spec.BAND_2GHZ
    174         else:
    175             return ap_spec.BAND_5GHZ
    176 
    177 
    178     def get_class(self):
    179         """@return string class for AP from config file"""
    180         return self.ap_config.get(self.bss, self.CONF_CLASS)
    181 
    182 
    183     def get_admin(self):
    184         """@return string admin for AP from config file"""
    185         return self.ap_config.get(self.bss, self.CONF_ADMIN)
    186 
    187 
    188     def get_admin_ip(self):
    189         """@return admin IP for AP from config file"""
    190         return self.ap_config.get(self.bss, self.CONF_ADMIN_IP)
    191 
    192 
    193     def power_off(self):
    194         """call rpm_client to power off AP"""
    195         rpm_client.set_power_afe(self.get_wan_host(), 'OFF')
    196 
    197 
    198     def power_on(self):
    199         """call rpm_client to power on AP"""
    200         rpm_client.set_power_afe(self.get_wan_host(), 'ON')
    201 
    202         # Hard coded timer for now to wait for the AP to come alive
    203         # before trying to use it.  We need scanning code
    204         # to scan until the AP becomes available (crosbug.com/36710).
    205         time.sleep(TIMEOUT)
    206 
    207 
    208     def __str__(self):
    209         """@return string description of AP"""
    210         ap_info = {
    211             'brand': self.get_brand(),
    212             'model': self.get_model(),
    213             'ssid' : self.get_ssid(),
    214             'bss'  : self.get_bss(),
    215             'hostname': self.get_wan_host(),
    216         }
    217         return ('AP Info:\n'
    218                 '  Name:      %(brand)s %(model)s\n'
    219                 '  SSID:      %(ssid)s\n'
    220                 '  BSS:       %(bss)s\n'
    221                 '  Hostname:  %(hostname)s\n' % ap_info)
    222