1# Lint as: python2, python3 2# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import collections 7import logging 8import os 9import time 10 11import six.moves.configparser 12 13from autotest_lib.client.common_lib import seven 14from autotest_lib.client.common_lib.cros.network import ap_constants 15from autotest_lib.server.cros.ap_configurators import ap_spec 16 17 18TIMEOUT = 100 19 20 21def get_ap_list(): 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 # chaos_ap_list.conf holds static conf of all APs in lab. 32 for filename in ['chaos_ap_list.conf']: 33 ap_config = seven.config_parser( 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 48class APPowerException(Exception): 49 """ Exception raised when AP fails to power on. """ 50 pass 51 52class APSectionError(Exception): 53 """ Exception raised when AP instance does not exist in the config. """ 54 pass 55 56RPMUnit = collections.namedtuple('RPMUnit', 'hostname outlet') 57 58class AP(object): 59 """ An instance of an ap defined in the chaos config file. 60 61 This object is a wrapper that can be used to retrieve information 62 about an AP in the chaos lab, and control its power. 63 64 """ 65 66 67 # Keys used in the config file. 68 CONF_SSID = 'ssid' 69 CONF_BRAND = 'brand' 70 CONF_MODEL = 'model' 71 CONF_WAN_MAC = 'wan mac' 72 CONF_WAN_HOST = 'wan_hostname' 73 CONF_RPM_MANAGED = 'rpm_managed' 74 CONF_RPM_HOSTNAME = 'rpm_hostname' 75 CONF_RPM_OUTLET = 'rpm_outlet' 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_unit(self): 129 """@return RPMUnit for this AP. None if AP is not managed via RPM.""" 130 if not self._get_rpm_managed(): 131 return None 132 return RPMUnit( 133 self.ap_config.get(self.bss, self.CONF_RPM_HOSTNAME), 134 self.ap_config.get(self.bss, self.CONF_RPM_OUTLET), 135 ) 136 137 138 def get_bss(self): 139 """@return string bss for AP from config file""" 140 try: 141 bss = self.ap_config.get(self.bss, self.CONF_BSS) 142 except six.moves.configparser.NoOptionError as e: 143 bss = 'N/A' 144 return bss 145 146 147 def get_bss5(self): 148 """@return string bss5 for AP from config file""" 149 try: 150 bss5 = self.ap_config.get(self.bss, self.CONF_BSS5) 151 except six.moves.configparser.NoOptionError as e: 152 bss5 = 'N/A' 153 return bss5 154 155 def get_bandwidth(self): 156 """@return string bandwidth for AP from config file""" 157 return self.ap_config.get(self.bss, self.CONF_BANDWIDTH) 158 159 160 def get_security(self): 161 """@return string security for AP from config file""" 162 return self.ap_config.get(self.bss, self.CONF_SECURITY) 163 164 165 def get_psk(self): 166 """@return string psk for AP from config file""" 167 return self.ap_config.get(self.bss, self.CONF_PSK) 168 169 170 def get_frequency(self): 171 """@return int frequency for AP from config file""" 172 return int(self.ap_config.get(self.bss, self.CONF_FREQUENCY)) 173 174 def get_channel(self): 175 """@return int channel for AP from config file""" 176 return ap_spec.CHANNEL_TABLE[self.get_frequency()] 177 178 179 def get_band(self): 180 """@return string band for AP from config file""" 181 if self.get_frequency() < 4915: 182 return ap_spec.BAND_2GHZ 183 else: 184 return ap_spec.BAND_5GHZ 185 186 187 def get_class(self): 188 """@return string class for AP from config file""" 189 return self.ap_config.get(self.bss, self.CONF_CLASS) 190 191 192 def get_admin(self): 193 """@return string admin for AP from config file""" 194 return self.ap_config.get(self.bss, self.CONF_ADMIN) 195 196 197 def get_admin_ip(self): 198 """@return admin IP for AP from config file""" 199 return self.ap_config.get(self.bss, self.CONF_ADMIN_IP) 200 201 202 def _get_rpm_managed(self): 203 return self.ap_config.getboolean(self.bss, self.CONF_RPM_MANAGED) 204 205 206 def __str__(self): 207 """@return string description of AP""" 208 ap_info = { 209 'brand': self.get_brand(), 210 'model': self.get_model(), 211 'ssid' : self.get_ssid(), 212 'bss' : self.get_bss(), 213 'hostname': self.get_wan_host(), 214 } 215 return ('AP Info:\n' 216 ' Name: %(brand)s %(model)s\n' 217 ' SSID: %(ssid)s\n' 218 ' BSS: %(bss)s\n' 219 ' Hostname: %(hostname)s\n' % ap_info) 220