1# Copyright (c) 2012 The Chromium 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"""File containing class to build all available ap_configurators."""
6
7import logging
8
9from autotest_lib.client.common_lib.cros.network import ap_constants
10from autotest_lib.server import site_utils
11from autotest_lib.server.cros import ap_config
12from autotest_lib.server.cros.ap_configurators import ap_cartridge
13from autotest_lib.server.cros.ap_configurators import ap_spec
14from autotest_lib.server.cros.dynamic_suite import frontend_wrappers
15
16
17class APConfiguratorFactory(object):
18    """Class that instantiates all available APConfigurators.
19
20    @attribute CONFIGURATOR_MAP: a dict of strings, mapping to model-specific
21                                 APConfigurator objects.
22    @attribute BANDS: a string, bands supported by an AP.
23    @attribute MODES: a string, 802.11 modes supported by an AP.
24    @attribute SECURITIES: a string, security methods supported by an AP.
25    @attribute HOSTNAMES: a string, AP hostname.
26    @attribute ap_list: a list of APConfigurator objects.
27    @attribute ap_config: an APConfiguratorConfig object.
28    """
29
30    PREFIX='autotest_lib.server.cros.ap_configurators.'
31    CONFIGURATOR_MAP = {
32        'LinksysAPConfigurator':
33            [PREFIX + 'linksys_ap_configurator',
34                'LinksysAPConfigurator'],
35        'LinksysAP15Configurator':
36            [PREFIX + 'linksys_ap_15_configurator',
37                'LinksysAP15Configurator'],
38        'DLinkAPConfigurator':
39            [PREFIX + 'dlink_ap_configurator',
40                'DLinkAPConfigurator'],
41        'TrendnetAPConfigurator':
42            [PREFIX + 'trendnet_ap_configurator',
43                'TrendnetAPConfigurator'],
44        'Trendnet691grAPConfigurator':
45            [PREFIX + 'trendnet691gr_ap_configurator',
46                'Trendnet691grAPConfigurator'],
47        'Trendnet731brAPConfigurator':
48            [PREFIX + 'trendnet731br_ap_configurator',
49                'Trendnet731brAPConfigurator'],
50        'Trendnet432brpAPConfigurator':
51            [PREFIX + 'trendnet432brp_ap_configurator',
52                'Trendnet432brpAPConfigurator'],
53        'Trendnet692grAPConfigurator':
54            [PREFIX + 'trendnet692gr_ap_configurator',
55                'Trendnet692grAPConfigurator'],
56        'Trendnet654trAPConfigurator':
57            [PREFIX + 'trendnet654tr_ap_configurator',
58                'Trendnet654trAPConfigurator'],
59        'Trendnet812druAPConfigurator':
60            [PREFIX + 'trendnet812dru_ap_configurator',
61                'Trendnet812druAPConfigurator'],
62        'DLinkDIR655APConfigurator':
63            [PREFIX + 'dlink_dir655_ap_configurator',
64                'DLinkDIR655APConfigurator'],
65        'DLinkDWL2100APConfigurator':
66            [PREFIX + 'dlink_dwl2100_ap_configurator',
67                'DLinkDWL2100APConfigurator'],
68        'DLinkDIR300APConfigurator':
69            [PREFIX + 'dlink_dir300_ap_configurator',
70                'DLinkDIR300APConfigurator'],
71        'DLinkDIR505lAPConfigurator':
72            [PREFIX + 'dlink_dir505l_ap_configurator',
73                'DLinkDIR505lAPConfigurator'],
74        'BuffaloAPConfigurator':
75            [PREFIX + 'buffalo_ap_configurator',
76                'BuffaloAPConfigurator'],
77        'BuffalowzrAPConfigurator':
78            [PREFIX + 'buffalo_wzr_d1800h_ap_configurator',
79                'BuffalowzrAPConfigurator'],
80        'Buffaloag300hAPConfigurator':
81            [PREFIX + 'buffaloag300h_ap_configurator',
82                'Buffaloag300hAPConfigurator'],
83        'BuffaloWSR1166DDAPConfigurator':
84            [PREFIX + 'buffalo_wsr_1166dd_ap_configurator',
85                'BuffaloWSR1166DDAPConfigurator'],
86        'AsusAPConfigurator':
87            [PREFIX + 'asus_ap_configurator',
88                'AsusAPConfigurator'],
89        'AsusQISAPConfigurator':
90            [PREFIX + 'asus_qis_ap_configurator',
91                'AsusQISAPConfigurator'],
92        'Asus66RAPConfigurator':
93            [PREFIX + 'asus_ac66r_ap_configurator',
94                'Asus66RAPConfigurator'],
95        'AsusRTAC68UAPConfigurator':
96            [PREFIX + 'asus_rtac68u_ap_configurator',
97                'AsusRTAC68UAPConfigurator'],
98        'Netgear3700APConfigurator':
99            [PREFIX + 'netgear3700_ap_configurator',
100                'Netgear3700APConfigurator'],
101        'Netgear3400APConfigurator':
102            [PREFIX + 'netgear3400_ap_configurator',
103                'Netgear3400APConfigurator'],
104        'NetgearR6200APConfigurator':
105            [PREFIX + 'netgearR6200_ap_configurator',
106                'NetgearR6200APConfigurator'],
107        'Netgear1000APConfigurator':
108            [PREFIX + 'netgear1000_ap_configurator',
109                'Netgear1000APConfigurator'],
110        'Netgear2000APConfigurator':
111            [PREFIX + 'netgear2000_ap_configurator',
112                'Netgear2000APConfigurator'],
113        'Netgear4300APConfigurator':
114            [PREFIX + 'netgear4300_ap_configurator',
115                'Netgear4300APConfigurator'],
116        'Netgear4500APConfigurator':
117            [PREFIX + 'netgear4500_ap_configurator',
118                'Netgear4500APConfigurator'],
119        'NetgearWNR1000V4APConfigurator':
120            [PREFIX + 'netgearwnr1000v4_ap_configurator',
121                'NetgearWNR1000V4APConfigurator'],
122        'LinksyseDualBandAPConfigurator':
123            [PREFIX + 'linksyse_dual_band_configurator',
124                'LinksyseDualBandAPConfigurator'],
125        'Linksyse2000APConfigurator':
126            [PREFIX + 'linksyse2000_ap_configurator',
127                'Linksyse2000APConfigurator'],
128        'LinksyseWRT320APConfigurator':
129            [PREFIX + 'linksyswrt320_ap_configurator',
130                'LinksysWRT320APConfigurator'],
131        'Linksyse1500APConfigurator':
132            [PREFIX + 'linksyse1500_ap_configurator',
133                'Linksyse1500APConfigurator'],
134        'LinksysWRT54GS2APConfigurator':
135            [PREFIX + 'linksyswrt54gs2_ap_configurator',
136                'LinksysWRT54GS2APConfigurator'],
137        'LinksysWRT600APConfigurator':
138            [PREFIX + 'linksyswrt600_ap_configurator',
139                'LinksysWRT600APConfigurator'],
140        'LinksysM10APConfigurator':
141            [PREFIX + 'linksysm10_ap_configurator',
142                'LinksysM10APConfigurator'],
143        'LinksysWRT54GLAPConfigurator':
144            [PREFIX + 'linksyswrt54gl_ap_configurator',
145                'LinksysWRT54GLAPConfigurator'],
146        'LinksysWRT610NAPConfigurator':
147            [PREFIX + 'linksyswrt610n_ap_configurator',
148                'LinksysWRT610NAPConfigurator'],
149        'LinksysWRT120NAPConfigurator':
150            [PREFIX + 'linksyswrt120n_ap_configurator',
151                'LinksysWRT120NAPConfigurator'],
152        'LevelOneAPConfigurator':
153            [PREFIX + 'levelone_ap_configurator',
154                'LevelOneAPConfigurator'],
155        'NetgearDualBandAPConfigurator':
156            [PREFIX + 'netgear_WNDR_dual_band_configurator',
157                'NetgearDualBandAPConfigurator'],
158        'BelkinAPConfigurator':
159            [PREFIX + 'belkin_ap_configurator',
160                'BelkinAPConfigurator'],
161        'BelkinF5D7234APConfigurator':
162            [PREFIX + 'belkinF5D7234_ap_configurator',
163                'BelkinF5D7234APConfigurator'],
164        'BelkinF5D8236APConfigurator':
165            [PREFIX + 'belkinF5D8236_ap_configurator',
166                'BelkinF5D8236APConfigurator'],
167        'BelkinF6D4230APConfigurator':
168            [PREFIX + 'belkinF6D4230_ap_configurator',
169                'BelkinF6D4230APConfigurator'],
170        'BelkinF7DAPConfigurator':
171            [PREFIX + 'belkinF7D_ap_configurator',
172                'BelkinF7DAPConfigurator'],
173        'BelkinF9K1002v4APConfigurator':
174            [PREFIX + 'belkinF9k1002v4_ap_configurator',
175                'BelkinF9K1002v4APConfigurator'],
176        'BelkinF7D1301APConfigurator':
177            [PREFIX + 'belkinF7D1301_ap_configurator',
178                'BelkinF7D1301APConfigurator'],
179        'BelkinF9KAPConfigurator':
180            [PREFIX + 'belkinF9K_ap_configurator',
181                'BelkinF9KAPConfigurator'],
182        'BelkinF9K1001APConfigurator':
183            [PREFIX + 'belkinF9K1001_ap_configurator',
184                'BelkinF9K1001APConfigurator'],
185        'BelkinF9K1102APConfigurator':
186            [PREFIX + 'belkinF9K1102_ap_configurator',
187                'BelkinF9K1102APConfigurator'],
188        'BelkinF9K1103APConfigurator':
189            [PREFIX + 'belkinF9K1103_ap_configurator',
190                'BelkinF9K1103APConfigurator'],
191        'BelkinF9K1105APConfigurator':
192            [PREFIX + 'belkinF9K1105_ap_configurator',
193                'BelkinF9K1105APConfigurator'],
194        'BelkinF7D5301APConfigurator':
195            [PREFIX + 'belkinF7D5301_ap_configurator',
196                'BelkinF7D5301APConfigurator'],
197        'BelkinWRTRAPConfigurator':
198            [PREFIX + 'belkinWRTR_ap_configurator',
199                'BelkinWRTRAPConfigurator'],
200        'MediaLinkAPConfigurator':
201            [PREFIX + 'medialink_ap_configurator',
202                'MediaLinkAPConfigurator'],
203        'NetgearSingleBandAPConfigurator':
204            [PREFIX + 'netgear_single_band_configurator',
205                'NetgearSingleBandAPConfigurator'],
206        'DLinkwbr1310APConfigurator':
207            [PREFIX + 'dlinkwbr1310_ap_configurator',
208                'DLinkwbr1310APConfigurator'],
209        'Linksyse2100APConfigurator':
210            [PREFIX + 'linksyse2100_ap_configurator',
211                'Linksyse2100APConfigurator'],
212        'LinksyseSingleBandAPConfigurator':
213            [PREFIX + 'linksyse_single_band_configurator',
214                'LinksyseSingleBandAPConfigurator'],
215        'Linksyse2500APConfigurator':
216            [PREFIX + 'linksyse2500_ap_configurator',
217                'Linksyse2500APConfigurator'],
218        'WesternDigitalN600APConfigurator':
219            [PREFIX + 'westerndigitaln600_ap_configurator',
220                'WesternDigitalN600APConfigurator'],
221        'Linksyse1000APConfigurator':
222            [PREFIX + 'linksyse1000_ap_configurator',
223                'Linksyse1000APConfigurator'],
224        'LinksysWRT160APConfigurator':
225            [PREFIX + 'linksyswrt160_ap_configurator',
226                'LinksysWRT160APConfigurator'],
227        'Keeboxw150nrAPConfigurator':
228            [PREFIX + 'keeboxw150nr_ap_configurator',
229                'Keeboxw150nrAPConfigurator'],
230        'EdimaxAPConfigurator':
231            [PREFIX + 'edimax_ap_configurator',
232                'EdimaxAPConfigurator'],
233        'Edimax6475ndAPConfigurator':
234            [PREFIX + 'edimax6475nd_ap_configurator',
235                'Edimax6475ndAPConfigurator'],
236        'Edimax6428nsAPConfigurator':
237            [PREFIX + 'edimax6428ns_ap_configurator',
238                'Edimax6428nsAPConfigurator'],
239        'StaticAPConfigurator':
240            [PREFIX + 'static_ap_configurator',
241                'StaticAPConfigurator'],
242    }
243
244    BANDS = 'bands'
245    MODES = 'modes'
246    SECURITIES = 'securities'
247    HOSTNAMES = 'hostnames'
248
249
250    def __init__(self, ap_test_type, spec=None):
251        webdriver_ready = False
252        self.ap_list = []
253        self.test_type = ap_test_type
254        for ap in ap_config.get_ap_list(ap_test_type):
255            module_name, configurator_class = \
256                    self.CONFIGURATOR_MAP[ap.get_class()]
257            module = __import__(module_name, fromlist=configurator_class)
258            configurator = module.__dict__[configurator_class]
259            self.ap_list.append(configurator(ap_config=ap))
260
261
262    def _get_aps_by_visibility(self, visible=True):
263        """Returns all configurators that support setting visibility.
264
265        @param visibility = True if SSID should be visible; False otherwise.
266
267        @returns aps: a set of APConfigurators"""
268        if visible:
269            return set(self.ap_list)
270
271        return set(filter(lambda ap: ap.is_visibility_supported(),
272                          self.ap_list))
273
274
275    def _get_aps_by_mode(self, band, mode):
276        """Returns all configurators that support a given 802.11 mode.
277
278        @param band: an 802.11 band.
279        @param mode: an 802.11 modes.
280
281        @returns aps: a set of APConfigurators.
282        """
283        if not mode:
284            return set(self.ap_list)
285
286        aps = []
287        for ap in self.ap_list:
288            modes = ap.get_supported_modes()
289            for d in modes:
290                if d['band'] == band and mode in d['modes']:
291                    aps.append(ap)
292        return set(aps)
293
294
295    def _get_aps_by_security(self, security):
296        """Returns all configurators that support a given security mode.
297
298        @param security: the security type
299
300        @returns aps: a set of APConfigurators.
301        """
302
303        if not security:
304            return set(self.ap_list)
305
306        aps = []
307        for ap in self.ap_list:
308            if ap.is_security_mode_supported(security):
309                aps.append(ap)
310        return set(aps)
311
312
313    def _get_aps_by_band(self, band, channel=None):
314        """Returns all APs that support a given band.
315
316        @param band: the band desired.
317
318        @returns aps: a set of APConfigurators.
319        """
320        if not band:
321            return set(self.ap_list)
322
323        aps = []
324        for ap in self.ap_list:
325            bands_and_channels = ap.get_supported_bands()
326            for d in bands_and_channels:
327                if channel:
328                    if d['band'] == band and channel in d['channels']:
329                        aps.append(ap)
330                elif d['band'] == band:
331                    aps.append(ap)
332        return set(aps)
333
334
335    def get_aps_by_hostnames(self, hostnames, ap_list=None):
336        """Returns specific APs by host name.
337
338        @param hostnames: a list of strings, AP's wan_hostname defined in the AP
339                          configuration file.
340        @param ap_list: a list of APConfigurator objects.
341
342        @return a list of APConfigurators.
343        """
344        if ap_list == None:
345            ap_list = self.ap_list
346
347        aps = []
348        for ap in ap_list:
349            if ap.host_name in hostnames:
350                logging.info('Found AP by hostname %s', ap.host_name)
351                aps.append(ap)
352
353        return aps
354
355
356    def _get_aps_by_configurator_type(self, configurator_type, ap_list):
357        """Returns APs that match the given configurator type.
358
359        @param configurator_type: the type of configurtor to return.
360
361        @return a list of APConfigurators.
362        """
363        aps = []
364        for ap in ap_list:
365            if ap.configurator_type == configurator_type:
366                aps.append(ap)
367
368        return aps
369
370
371    def _get_aps_by_lab_location(self, want_chamber_aps, ap_list):
372        """Returns APs that are inside or outside of the chaos/clique lab.
373
374        @param want_chamber_aps: True to select only APs in the chaos/clique
375        chamber. False to select APs outside of the chaos/clique chamber.
376
377        @return a list of APConfigurators
378        """
379        aps = []
380        afe = frontend_wrappers.RetryingAFE(
381                timeout_min=10, delay_sec=5, server=site_utils.get_global_afe_hostname())
382        if self.test_type == ap_constants.AP_TEST_TYPE_CHAOS:
383            ap_label = 'chaos_ap'
384            lab_label = 'chaos_chamber'
385        elif self.test_type == ap_constants.AP_TEST_TYPE_CLIQUE:
386            ap_label = 'clique_ap'
387            lab_label = 'clique_chamber'
388        elif self.test_type == ap_constants.AP_TEST_TYPE_CASEY5:
389            ap_label = 'casey_ap5'
390            lab_label = 'casey_chamber5'
391        elif self.test_type == ap_constants.AP_TEST_TYPE_CASEY7:
392            ap_label = 'casey_ap7'
393            lab_label = 'casey_chamber7'
394        else:
395            return None
396        all_aps = set(afe.get_hostnames(label=ap_label))
397        chamber_devices = set(afe.get_hostnames(label=lab_label))
398        chamber_aps = all_aps.intersection(chamber_devices)
399        for ap in ap_list:
400            if want_chamber_aps and ap.host_name in chamber_aps:
401                aps.append(ap)
402
403            if not want_chamber_aps and ap.host_name not in chamber_aps:
404                aps.append(ap)
405
406        return aps
407
408
409    def get_ap_configurators_by_spec(self, spec=None, pre_configure=False):
410        """Returns available configurators meeting spec.
411
412        @param spec: a validated ap_spec object
413        @param pre_configure: boolean, True to set all of the configuration
414                              options for the APConfigurator object using the
415                              given ap_spec; False otherwise.  An ap_spec must
416                              be passed for this to have any effect.
417        @returns aps: a list of APConfigurator objects
418        """
419        if not spec:
420            return self.ap_list
421
422        # APSpec matching is exact.  With the exception of lab location, even
423        # if a hostname is passed the capabilities of a given configurator
424        # much match everything in the APSpec.  This helps to prevent failures
425        # during the pre-scan phase.
426        aps = self._get_aps_by_band(spec.band, channel=spec.channel)
427        aps &= self._get_aps_by_mode(spec.band, spec.mode)
428        aps &= self._get_aps_by_security(spec.security)
429        aps &= self._get_aps_by_visibility(spec.visible)
430        matching_aps = list(aps)
431        # If APs hostnames are provided, assume the tester knows the location
432        # of the AP and skip AFE calls.
433        if spec.hostnames is None:
434            matching_aps = self._get_aps_by_lab_location(spec.lab_ap,
435                                                         matching_aps)
436
437        if spec.configurator_type != ap_spec.CONFIGURATOR_ANY:
438            matching_aps = self._get_aps_by_configurator_type(
439                           spec.configurator_type, matching_aps)
440        if spec.hostnames is not None:
441            matching_aps = self.get_aps_by_hostnames(spec.hostnames,
442                                                     ap_list=matching_aps)
443        if pre_configure:
444            for ap in matching_aps:
445                ap.set_using_ap_spec(spec)
446        return matching_aps
447
448
449    def turn_off_all_routers(self, broken_pdus):
450        """Powers down all of the routers.
451
452        @param broken_pdus: list of bad/offline PDUs.
453        """
454        ap_power_cartridge = ap_cartridge.APCartridge()
455        for ap in self.ap_list:
456            ap.power_down_router()
457            ap_power_cartridge.push_configurator(ap)
458        ap_power_cartridge.run_configurators(broken_pdus)
459