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