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