blob: 52b6ac67db78b33e9ee196c6ebb14c0d4c3cb1ef [file] [log] [blame]
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import ConfigParser
import logging
import os
import time
from autotest_lib.site_utils.rpm_control_system import rpm_client
TIMEOUT = 100
class APPowerException(Exception):
""" Exception raised when AP fails to power on. """
pass
class APSectionError(Exception):
""" Exception raised when AP instance does not exist in the config. """
pass
class ChaosAP(object):
""" An instance of an ap defined in the chaos config file.
This object is a wrapper that can be used to retrieve information
about an AP in the chaos lab, and control its power.
"""
# Keys used in the config file.
CONF_SSID = 'ssid'
CONF_BRAND = 'brand'
CONF_MODEL = 'model'
CONF_WAN_MAC = 'wan mac'
CONF_WAN_HOST = 'wan_hostname'
CONF_BSS = 'bss'
CONF_BSS5 = 'bss5'
CONF_BANDWIDTH = 'bandwidth'
CONF_SECURITY = 'security'
CONF_PSK = 'psk'
CONF_FREQUENCY = 'frequency'
CONF_BAND = 'band'
CONF_CHANNEL = 'channel'
CONF_CLASS = 'class_name'
CONF_ADMIN = 'admin_url'
# Frequency to channel conversion table
CHANNEL_TABLE = {2412: 1, 2417: 2, 2422: 3,
2427: 4, 2432: 5, 2437: 6,
2442: 7, 2447: 8, 2452: 9,
2457: 10, 2462: 11, 2467: 12,
2472: 13, 2484: 14, 5180: 36,
5200: 40, 5220: 44, 5240: 48,
5745: 149, 5765: 153, 5785: 157,
5805: 161, 5825: 165}
# This only works because the frequency table is
# one to one for Channels/Frequencies.
FREQUENCY_TABLE = dict((v,k) for k,v in CHANNEL_TABLE.iteritems())
# Needed for ap_configurator interoperability
BAND_2GHZ = '2.4GHz'
BAND_5GHZ = '5GHz'
def __init__(self, bss, config):
if not config.has_section(bss):
raise APSectionError('BSS (%s) not defined.' % bss)
self.bss = bss
self.ap_config = config
def get_ssid(self):
return self.ap_config.get(self.bss, self.CONF_SSID)
def get_brand(self):
return self.ap_config.get(self.bss, self.CONF_BRAND)
def get_model(self):
return self.ap_config.get(self.bss, self.CONF_MODEL)
def get_wan_mac(self):
return self.ap_config.get(self.bss, self.CONF_WAN_MAC)
def get_wan_host(self):
return self.ap_config.get(self.bss, self.CONF_WAN_HOST)
def get_bss(self):
return self.ap_config.get(self.bss, self.CONF_BSS)
def get_bss5(self):
return self.ap_config.get(self.bss, self.CONF_BSS5)
def get_bandwidth(self):
return self.ap_config.get(self.bss, self.CONF_BANDWIDTH)
def get_security(self):
return self.ap_config.get(self.bss, self.CONF_SECURITY)
def get_psk(self):
return self.ap_config.get(self.bss, self.CONF_PSK)
def get_frequency(self):
return self.ap_config.get(self.bss, self.CONF_FREQUENCY)
def get_channel(self):
return self.CHANNEL_TABLE[self.get_frequency()]
def get_band(self):
if int(frequency) < 4915:
return self.BAND_2GHZ
else:
return self.BAND_5GHZ
def get_class(self):
return self.ap_config.get(self.bss, self.CONF_CLASS)
def get_admin(self):
return self.ap_config.get(self.bss, self.CONF_ADMIN)
def power_off(self):
rpm_client.set_power(self.get_wan_host(), 'OFF')
def power_on(self):
rpm_client.set_power(self.get_wan_host(), 'ON')
# Hard coded timer for now to wait for the AP to come alive
# before trying to use it. We need scanning code
# to scan until the AP becomes available (crosbug.com/36710).
time.sleep(TIMEOUT)
def __str__(self):
ap_info = {
'brand': self.get_brand(),
'model': self.get_model(),
'ssid' : self.get_ssid(),
'bss' : self.get_bss(),
'hostname': self.get_wan_host(),
}
return ('AP Info:\n'
' Name: %(brand)s %(model)s\n'
' SSID: %(ssid)s\n'
' BSS: %(bss)s\n'
' Hostname: %(hostname)s\n' % ap_info)
class ChaosAPList(object):
""" Object containing information about all AP's in the chaos lab. """
DYNAMIC_AP_CONFIG_FILE = 'chaos_dynamic_ap_list.conf'
STATIC_AP_CONFIG_FILE = 'chaos_static_ap_list.conf'
def __init__(self, static_config=True):
self.ap_config = ConfigParser.RawConfigParser()
if static_config:
config_file = self.STATIC_AP_CONFIG_FILE
else:
config_file = self.DYNAMIC_AP_CONFIG_FILE
path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
config_file)
logging.debug('Reading config from "%s"', path)
self.ap_config.read(path)
def get_ap_by_bss(self, bss):
return ChaosAP(bss, self.ap_config)
def next(self):
bss = self._iterptr.next()
return self.get_ap_by_bss(bss)
def __iter__(self):
self._iterptr = self.ap_config.sections().__iter__()
return self