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