blob: 10d9d28eda38813e170ca15a010e6e1ab5a17088 [file] [log] [blame]
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""File containing class to build all available ap_configurators."""
import logging
from autotest_lib.server.cros import chaos_config
from autotest_lib.server.cros.chaos_ap_configurators import ap_cartridge
from autotest_lib.server.cros.chaos_ap_configurators import \
ap_configurator_config
import asus_ap_configurator
import asus_ac66r_ap_configurator
import asus_qis_ap_configurator
import belkin_ap_configurator
import belkinF9K_ap_configurator
import buffalo_ap_configurator
import buffalo_wzr_d1800h_ap_configurator
import dlink_ap_configurator
import dlink_dir655_ap_configurator
import dlinkwbr1310_ap_configurator
import keeboxw150nr_ap_configurator
import linksys_ap_configurator
import linksys_ap_15_configurator
import linksyse_dual_band_configurator
import linksyse_single_band_configurator
import linksyse1000_ap_configurator
import linksyse2000_ap_configurator
import linksyse2100_ap_configurator
import linksyse2500_ap_configurator
import linksyswrt160_ap_configurator
import medialink_ap_configurator
import netgear3700_ap_configurator
import netgear4300_ap_configurator
import netgearR6200_ap_configurator
import netgear1000_ap_configurator
import netgear2000_ap_configurator
import netgear_WNDR_dual_band_configurator
import netgear_single_band_configurator
import trendnet_ap_configurator
import trendnet691gr_ap_configurator
import trendnet731br_ap_configurator
import westerndigitaln600_ap_configurator
class APConfiguratorFactory(object):
"""Class that instantiates all available APConfigurators.
@attribute CONFIGURATOR_MAP: a dict of strings, mapping to model-specific
APConfigurator objects.
@attribute BANDS: a string, bands supported by an AP.
@attribute MODES: a string, 802.11 modes supported by an AP.
@attribute SECURITIES: a string, security methods supported by an AP.
@attribute HOSTNAMES: a string, AP hostname.
@attribute ap_list: a list of APConfigurator objects.
@attribute ap_config: an APConfiguratorConfig object.
"""
CONFIGURATOR_MAP = {
'LinksysAPConfigurator':
linksys_ap_configurator.LinksysAPConfigurator,
'LinksysAP15Configurator':
linksys_ap_15_configurator.LinksysAP15Configurator,
'DLinkAPConfigurator':
dlink_ap_configurator.DLinkAPConfigurator,
'TrendnetAPConfigurator':
trendnet_ap_configurator.TrendnetAPConfigurator,
'Trendnet691grAPConfigurator':
trendnet691gr_ap_configurator.Trendnet691grAPConfigurator,
'Trendnet731brAPConfigurator':
trendnet731br_ap_configurator.Trendnet731brAPConfigurator,
'DLinkDIR655APConfigurator':
dlink_dir655_ap_configurator.DLinkDIR655APConfigurator,
'BuffaloAPConfigurator':
buffalo_ap_configurator.BuffaloAPConfigurator,
'BuffalowzrAPConfigurator':
buffalo_wzr_d1800h_ap_configurator.BuffalowzrAPConfigurator,
'AsusAPConfigurator':
asus_ap_configurator.AsusAPConfigurator,
'AsusQISAPConfigurator':
asus_qis_ap_configurator.AsusQISAPConfigurator,
'Asus66RAPConfigurator':
asus_ac66r_ap_configurator.Asus66RAPConfigurator,
'Netgear3700APConfigurator':
netgear3700_ap_configurator.Netgear3700APConfigurator,
'NetgearR6200APConfigurator':
netgearR6200_ap_configurator.NetgearR6200APConfigurator,
'Netgear1000APConfigurator':
netgear1000_ap_configurator.Netgear1000APConfigurator,
'Netgear2000APConfigurator':
netgear2000_ap_configurator.Netgear2000APConfigurator,
'Netgear4300APConfigurator':
netgear4300_ap_configurator.Netgear4300APConfigurator,
'LinksyseDualBandAPConfigurator':
linksyse_dual_band_configurator.LinksyseDualBandAPConfigurator,
'Linksyse2000APConfigurator':
linksyse2000_ap_configurator.Linksyse2000APConfigurator,
'NetgearDualBandAPConfigurator':
netgear_WNDR_dual_band_configurator.NetgearDualBandAPConfigurator,
'BelkinAPConfigurator':
belkin_ap_configurator.BelkinAPConfigurator,
'BelkinF9KAPConfigurator':
belkinF9K_ap_configurator.BelkinF9KAPConfigurator,
'MediaLinkAPConfigurator':
medialink_ap_configurator.MediaLinkAPConfigurator,
'NetgearSingleBandAPConfigurator':
netgear_single_band_configurator.NetgearSingleBandAPConfigurator,
'DLinkwbr1310APConfigurator':
dlinkwbr1310_ap_configurator.DLinkwbr1310APConfigurator,
'Linksyse2100APConfigurator':
linksyse2100_ap_configurator.Linksyse2100APConfigurator,
'LinksyseSingleBandAPConfigurator':
linksyse_single_band_configurator.LinksyseSingleBandAPConfigurator,
'Linksyse2500APConfigurator':
linksyse2500_ap_configurator.Linksyse2500APConfigurator,
'WesternDigitalN600APConfigurator':
westerndigitaln600_ap_configurator.WesternDigitalN600APConfigurator,
'Linksyse1000APConfigurator':
linksyse1000_ap_configurator.Linksyse1000APConfigurator,
'LinksysWRT160APConfigurator':
linksyswrt160_ap_configurator.LinksysWRT160APConfigurator,
'Keeboxw150nrAPConfigurator':
keeboxw150nr_ap_configurator.Keeboxw150nrAPConfigurator,
}
BANDS = 'bands'
MODES = 'modes'
SECURITIES = 'securities'
HOSTNAMES = 'hostnames'
def __init__(self):
chaos_ap_list = chaos_config.ChaosAPList()
self.ap_list = []
for ap in chaos_ap_list:
configurator = self.CONFIGURATOR_MAP[ap.get_class()]
self.ap_list.append(configurator(ap_config=ap))
def _cleanup_ap_spec(self, key, value):
"""Validates AP attribute.
@param key: a string, one of BANDS, SECURITIES or MODES.
@param value: a list of strings, values of key.
@returns a list of strings, valid values for key. Or None.
"""
# Used to fetch AP attributes such as bands, modes, securities
config = ap_configurator_config.APConfiguratorConfig()
attr_dict = {
self.BANDS: config.VALID_BANDS,
self.MODES: config.VALID_MODES,
self.SECURITIES: config.VALID_SECURITIES,
}
invalid_value = set(value).difference(attr_dict[key])
if invalid_value:
logging.warning('Ignored invalid %s: %r', key, invalid_value)
value = list(set(value) - invalid_value)
logging.info('Remaining valid value for %s = %r', key, value)
return value
def _get_aps_with_modes(self, modes, ap_list):
"""Returns all configurators that support a given 802.11 mode.
@param mode: a list of hex numbers, 802.11 modes.
@param ap_list: a list of APConfigurator objects.
@returns aps: a list of APConfigurators. Or None.
"""
modes = self._cleanup_ap_spec(self.MODES, modes)
if not modes:
logging.warning('No valid modes found.')
return None
aps = []
for ap in ap_list:
bands_and_modes = ap.get_supported_modes()
# FIXME(tgao): would mixing modes across bands cause any issue?
ap_modes = set()
for d in bands_and_modes:
if self.MODES in d:
ap_modes = ap_modes.union(set(d[self.MODES]))
if set(modes).issubset(ap_modes):
logging.debug('Found ap by mode = %r', ap.host_name)
aps.append(ap)
return aps
def _get_aps_with_securities(self, securities, ap_list):
"""Returns all configurators that support a given security mode.
@param securities: a list of integers, security mode.
@param ap_list: a list of APConfigurator objects.
@returns aps: a list of APConfigurators. Or None.
"""
securities = self._cleanup_ap_spec(self.SECURITIES, securities)
if not securities:
logging.warning('No valid security found.')
return None
aps = []
for ap in ap_list:
for security in securities:
if not ap.is_security_mode_supported(security):
break
else: # ap supports all securities
logging.debug('Found ap by security = %r', ap.host_name)
aps.append(ap)
return aps
def _get_aps_with_bands(self, bands, ap_list):
"""Returns all APs that support bands.
@param bands: a list of strings, bands supported.
@param ap_list: a list of APConfigurator objects.
@returns aps: a list of APConfigurators. Or None.
"""
bands = self._cleanup_ap_spec(self.BANDS, bands)
if not bands:
logging.warning('No valid bands found.')
return None
aps = []
for ap in ap_list:
bands_and_channels = ap.get_supported_bands()
ap_bands = [d['band'] for d in bands_and_channels if 'band' in d]
if set(bands).issubset(set(ap_bands)):
logging.debug('Found ap by band = %r', ap.host_name)
aps.append(ap)
return aps
def _get_aps_with_hostnames(self, hostnames, ap_list):
"""Returns specific APs by host name.
@param hostnames: a list of strings, AP's wan_hostname defined in
../chaos_dynamic_ap_list.conf.
@param ap_list: a list of APConfigurator objects.
@return a list of APConfigurators.
"""
aps = []
for ap in ap_list:
if ap.host_name in hostnames:
logging.info('Found AP by hostname %s', ap.host_name)
aps.append(ap)
return aps
def get_ap_configurators(self, spec=None):
"""Returns available configurators meeting spec.
Caller may request APs based on the following attributes:
- BANDS, a list of strings, bands supported.
- MODES, a list of hex numbers, 802.11 modes supported.
- SECURITIES, a list of strings, security methods supported.
- HOSTNAMES, a list of strings, AP wan_hostname.
Interpretation rules:
- if an attribute is not present in spec, it's not used to select APs.
- caller should only specify an attribute s/he cares about testing.
- if HOSTNAMES is specified, only the APs specified are returned.
All other attributes are IGNORED.
- in case of a list of (>1) strings, logical AND is applied, e.g.
dual-band (2.4GHz AND 5GHz).
- if multiple attributes are specified, logical AND is applied.
Evaluation order is securities, then bands, then modes (which could
depend on bands as input).
Sample spec values and expected returns:
1. spec = None or empty dict
Return all APs
2. spec = dict(bands=['2.4GHz', '5GHz'])
Return all dual-band APs
3. spec = dict(modes=[0x00010, 0x00100], securities=[2])
Return all APs which support both 802.11b AND 802.11g modes AND
PSK security
4. spec = dict(hostnames=['chromeos3-row1-rack1-host6',
'chromeos3-row1-rack1-host7'])
Return only the two APs specified.
@param spec: a dict of AP attributes, see explanation above.
@returns aps: a list of APConfigurator objects. Or None.
"""
aps = self.ap_list
if not spec:
logging.info('No spec included, return all APs')
return aps
hostnames = spec.get(self.HOSTNAMES, None)
if hostnames: # Fast path to return specified APs
logging.info('Select APs by hostname: %r', hostnames)
aps = self._get_aps_with_hostnames(hostnames, aps)
return aps
securities = spec.get(self.SECURITIES, None)
bands = spec.get(self.BANDS, None)
modes = spec.get(self.MODES, None)
if securities:
logging.info('Select APs by securities: %r', securities)
aps = self._get_aps_with_securities(securities, aps)
if aps and bands:
logging.info('Select APs by bands: %r', bands)
aps = self._get_aps_with_bands(bands, aps)
if aps and modes:
logging.info('Select APs by modes: %r', modes)
aps = self._get_aps_with_modes(modes, aps)
return aps
def turn_off_all_routers(self):
"""Powers down all of the routers."""
ap_power_cartridge = ap_cartridge.APCartridge()
for ap in self.ap_list:
ap.power_down_router()
ap_power_cartridge.push_configurator(ap)
ap_power_cartridge.run_configurators()