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 six.moves.configparser 8import logging 9import os 10import time 11 12from autotest_lib.client.common_lib.cros.network import ap_constants 13from autotest_lib.server.cros.ap_configurators import ap_spec 14 15 16TIMEOUT = 100 17 18 19def get_ap_list(): 20 """ 21 Returns the list of AP's from the corresponding configuration file. 22 23 @param ap_test_type: Used to determine which type of test we're 24 currently running (Chaos vs Clique). 25 @returns a list of AP objects. 26 27 """ 28 aps = [] 29 # chaos_ap_list.conf holds static conf of all APs in lab. 30 for filename in ['chaos_ap_list.conf']: 31 ap_config = six.moves.configparser.RawConfigParser( 32 {AP.CONF_RPM_MANAGED: 'False'}) 33 path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 34 filename) 35 if not os.path.exists(path): 36 logging.warning('Skipping missing config: "%s"', path) 37 continue 38 39 logging.debug('Reading config from: "%s"', path) 40 ap_config.read(path) 41 for bss in ap_config.sections(): 42 aps.append(AP(bss, ap_config)) 43 return aps 44 45 46class APPowerException(Exception): 47 """ Exception raised when AP fails to power on. """ 48 pass 49 50class APSectionError(Exception): 51 """ Exception raised when AP instance does not exist in the config. """ 52 pass 53 54RPMUnit = collections.namedtuple('RPMUnit', 'hostname outlet') 55 56class 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_RPM_HOSTNAME = 'rpm_hostname' 73 CONF_RPM_OUTLET = 'rpm_outlet' 74 CONF_BSS = 'bss' 75 CONF_BSS5 = 'bss5' 76 CONF_BANDWIDTH = 'bandwidth' 77 CONF_SECURITY = 'security' 78 CONF_PSK = 'psk' 79 CONF_FREQUENCY = 'frequency' 80 CONF_BAND = 'band' 81 CONF_CHANNEL = 'channel' 82 CONF_CLASS = 'class_name' 83 CONF_ADMIN = 'admin_url' 84 CONF_ADMIN_IP = 'admin_ip' 85 86 87 def __init__(self, bss, config): 88 """ 89 Intialize object 90 91 @param bss: string containing bssid 92 @param config: ConfigParser read from file 93 94 """ 95 if not config.has_section(bss): 96 raise APSectionError('BSS (%s) not defined.' % bss) 97 self.bss = bss 98 self.ap_config = config 99 100 101 def get_ssid(self): 102 """@return string ssid for AP from config file""" 103 return self.ap_config.get(self.bss, self.CONF_SSID) 104 105 106 def get_brand(self): 107 """@return string brand for AP from config file""" 108 return self.ap_config.get(self.bss, self.CONF_BRAND) 109 110 111 def get_model(self): 112 """@return string model for AP from config file""" 113 return self.ap_config.get(self.bss, self.CONF_MODEL) 114 115 116 def get_wan_mac(self): 117 """@return string mac for WAN port of AP from config file""" 118 return self.ap_config.get(self.bss, self.CONF_WAN_MAC) 119 120 121 def get_wan_host(self): 122 """@return string host for AP from config file""" 123 return self.ap_config.get(self.bss, self.CONF_WAN_HOST) 124 125 126 def get_rpm_unit(self): 127 """@return RPMUnit for this AP. None if AP is not managed via RPM.""" 128 if not self._get_rpm_managed(): 129 return None 130 return RPMUnit( 131 self.ap_config.get(self.bss, self.CONF_RPM_HOSTNAME), 132 self.ap_config.get(self.bss, self.CONF_RPM_OUTLET), 133 ) 134 135 136 def get_bss(self): 137 """@return string bss for AP from config file""" 138 try: 139 bss = self.ap_config.get(self.bss, self.CONF_BSS) 140 except six.moves.configparser.NoOptionError as e: 141 bss = 'N/A' 142 return bss 143 144 145 def get_bss5(self): 146 """@return string bss5 for AP from config file""" 147 try: 148 bss5 = self.ap_config.get(self.bss, self.CONF_BSS5) 149 except six.moves.configparser.NoOptionError as e: 150 bss5 = 'N/A' 151 return bss5 152 153 def get_bandwidth(self): 154 """@return string bandwidth for AP from config file""" 155 return self.ap_config.get(self.bss, self.CONF_BANDWIDTH) 156 157 158 def get_security(self): 159 """@return string security for AP from config file""" 160 return self.ap_config.get(self.bss, self.CONF_SECURITY) 161 162 163 def get_psk(self): 164 """@return string psk for AP from config file""" 165 return self.ap_config.get(self.bss, self.CONF_PSK) 166 167 168 def get_frequency(self): 169 """@return int frequency for AP from config file""" 170 return int(self.ap_config.get(self.bss, self.CONF_FREQUENCY)) 171 172 def get_channel(self): 173 """@return int channel for AP from config file""" 174 return ap_spec.CHANNEL_TABLE[self.get_frequency()] 175 176 177 def get_band(self): 178 """@return string band for AP from config file""" 179 if self.get_frequency() < 4915: 180 return ap_spec.BAND_2GHZ 181 else: 182 return ap_spec.BAND_5GHZ 183 184 185 def get_class(self): 186 """@return string class for AP from config file""" 187 return self.ap_config.get(self.bss, self.CONF_CLASS) 188 189 190 def get_admin(self): 191 """@return string admin for AP from config file""" 192 return self.ap_config.get(self.bss, self.CONF_ADMIN) 193 194 195 def get_admin_ip(self): 196 """@return admin IP for AP from config file""" 197 return self.ap_config.get(self.bss, self.CONF_ADMIN_IP) 198 199 200 def _get_rpm_managed(self): 201 return self.ap_config.getboolean(self.bss, self.CONF_RPM_MANAGED) 202 203 204 def __str__(self): 205 """@return string description of AP""" 206 ap_info = { 207 'brand': self.get_brand(), 208 'model': self.get_model(), 209 'ssid' : self.get_ssid(), 210 'bss' : self.get_bss(), 211 'hostname': self.get_wan_host(), 212 } 213 return ('AP Info:\n' 214 ' Name: %(brand)s %(model)s\n' 215 ' SSID: %(ssid)s\n' 216 ' BSS: %(bss)s\n' 217 ' Hostname: %(hostname)s\n' % ap_info) 218