• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 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
5import collections
6import pprint
7import re
8import xmlrpclib
9
10from autotest_lib.client.common_lib import global_config
11from autotest_lib.client.common_lib.cros.network import ap_constants
12from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
13from autotest_lib.client.common_lib.cros.network import xmlrpc_security_types
14from autotest_lib.server.cros.ap_configurators import ap_configurator
15from autotest_lib.server.cros.ap_configurators import ap_spec
16
17CartridgeCmd = collections.namedtuple('CartridgeCmd', ['method', 'args'])
18RPM_FRONTEND_SERVER = global_config.global_config.get_config_value(
19        'CROS', 'rpm_frontend_uri')
20
21# DHCP delayed devices.  Some APs need additional time for the DHCP
22# server to come on-line.  These are AP based, so the BSS is used
23# since that is unique.
24DHCP_DELAY_DEVICES=['44:94:fc:71:88:9b', # Netgear wndr4300
25                    '10:0d:7f:4d:68:3c', # Netgear wndr3700v4
26                    '14:35:8b:0b:6c:80', # Medialink mwn_wapr150nv2
27                    '20:4e:7f:49:86:8f'] # Netgear wpn824n
28
29class StaticAPConfigurator(ap_configurator.APConfiguratorAbstract):
30    """Derived class to supply AP configuration information."""
31
32
33    def __init__(self, ap_config):
34        """
35        Initialize instance
36
37        @param ap_config: AP object to configure this instance
38
39        """
40        super(StaticAPConfigurator, self).__init__()
41        self._command_list = list()
42
43        # This allows the ability to build a generic configurator
44        # which can be used to get access to the members above.
45        self.class_name = ap_config.get_class()
46        self._short_name = ap_config.get_model()
47        self.mac_address = ap_config.get_wan_mac()
48        self.host_name = ap_config.get_wan_host()
49        # Get corresponding PDU from host name.
50        self.pdu = re.sub('host\d+', 'rpm1', self.host_name) + '.cros'
51        self.channel = ap_config.get_channel()
52        self.band = ap_config.get_band()
53        self.current_band = ap_config.get_band()
54        self.security = ap_config.get_security()
55        if self.security == ap_spec.SECURITY_TYPE_MIXED:
56           self.security = [ap_spec.SECURITY_TYPE_WPA2PSK,
57                            ap_spec.SECURITY_TYPE_WPAPSK]
58        else:
59           self.security = [self.security]
60        self.psk = ap_config.get_psk()
61        self._ssid = ap_config.get_ssid()
62        self.rpm_unit = ap_config.get_rpm_unit()
63
64        self._configuration_success = ap_constants.CONFIG_SUCCESS
65        self.config_data = ap_config
66
67        name_dict = {'Router name': self._short_name,
68                     'Controller class': self.class_name,
69                     '2.4 GHz MAC Address': ap_config.get_bss(),
70                     '5 GHz MAC Address': ap_config.get_bss5(),
71                     'Hostname': ap_config.get_wan_host()}
72
73        self._name = pprint.pformat(name_dict)
74
75        # Check if a delay needs to be added for this AP.
76        if (ap_config.get_bss() in DHCP_DELAY_DEVICES or
77            ap_config.get_bss5() in DHCP_DELAY_DEVICES):
78            self._dhcp_delay = 60
79
80        self.rpm_client = xmlrpclib.ServerProxy(RPM_FRONTEND_SERVER,
81                                                verbose=False,
82                                                allow_none=True)
83
84
85    def __str__(self):
86        """Prettier display of the object"""
87        return('AP Name: %s\n'
88               'BSS: %s\n'
89               'SSID: %s\n'
90               'Short name: %s' % (self.name,
91                   self.config_data.get_bss(), self._ssid,
92                   self.short_name))
93
94
95    @property
96    def ssid(self):
97        """Returns the SSID."""
98        return self._ssid
99
100
101    def power_down_router(self):
102        """power down via rpm"""
103        self._append_rpm_command('OFF')
104
105
106    def power_up_router(self):
107        """power up via rpm"""
108        self._append_rpm_command('ON')
109
110
111    def _append_rpm_command(self, command):
112        if self.rpm_unit is None:
113            return
114
115        self._command_list.append(CartridgeCmd(
116                self.rpm_client.set_power_via_rpm,
117                [
118                        self.host_name,
119                        self.rpm_unit.hostname,
120                        self.rpm_unit.outlet,
121                        None,
122                        command,
123                ],
124        ))
125
126
127    def set_using_ap_spec(self, set_ap_spec, power_up=True):
128        """
129        Sets all configurator options.
130
131        Note: for StaticAPs there is no config required, so the only action
132        here is to power up if needed
133
134        @param set_ap_spec: APSpec object
135
136        """
137        if power_up:
138            self.power_up_router()
139
140
141    def apply_settings(self):
142        """Allow cartridge to run commands in _command_list"""
143        self.check_pdu_status()
144        for command in self._command_list:
145            command.method(*command.args)
146
147
148    def reset_command_list(self):
149        """Resets all internal command state."""
150        self._command_list = list()
151
152
153    @property
154    def name(self):
155        """Returns a string to describe the router."""
156        return self._name
157
158
159    @property
160    def short_name(self):
161        """Returns a short string to describe the router."""
162        return self._short_name
163
164
165    def get_supported_bands(self):
166        """Returns a list of dictionaries describing the supported bands.
167
168        Example: returned is a dictionary of band and a list of channels. The
169                 band object returned must be one of those defined in the
170                 __init___ of this class.
171
172        supported_bands = [{'band' : self.band_2GHz,
173                            'channels' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]},
174                           {'band' : self.band_5ghz,
175                            'channels' : [26, 40, 44, 48, 149, 153, 165]}]
176
177        @return a list of dictionaries as described above
178
179        """
180        supported_bands = [{'band' : self.band,
181                            'channels' : [self.channel]}]
182
183        return supported_bands
184
185
186    def get_supported_modes(self):
187        """
188        Returns a list of dictionaries describing the supported modes.
189
190        Example: returned is a dictionary of band and a list of modes. The band
191                 and modes objects returned must be one of those defined in the
192                 __init___ of this class.
193
194        supported_modes = [{'band' : ap_spec.BAND_2GHZ,
195                            'modes' : [mode_b, mode_b | mode_g]},
196                           {'band' : ap_spec.BAND_5GHZ,
197                            'modes' : [mode_a, mode_n, mode_a | mode_n]}]
198
199        @return a list of dictionaries as described above
200
201        """
202        supported_modes = [{'band' : self.band,
203                            'modes' : [ap_spec.DEFAULT_5GHZ_MODE
204                    if self.channel in ap_spec.VALID_5GHZ_CHANNELS
205                    else ap_spec.DEFAULT_2GHZ_MODE]}]
206
207        return supported_modes
208
209
210    def is_visibility_supported(self):
211        """
212        Returns if AP supports setting the visibility (SSID broadcast).
213
214        @return False
215
216        """
217        return False
218
219
220    def is_band_and_channel_supported(self, band, channel):
221        """
222        Returns if a given band and channel are supported.
223
224        @param band: the band to check if supported
225        @param channel: the channel to check if supported
226
227        @return True if combination is supported; False otherwise.
228
229        """
230        bands = self.get_supported_bands()
231        for current_band in bands:
232            if (current_band['band'] == band and
233                channel in current_band['channels']):
234                return True
235        return False
236
237
238    def is_security_mode_supported(self, security_mode):
239        """
240        Returns if a given security_type is supported.
241
242        @param security_mode: one of the following modes:
243                         self.security_disabled,
244                         self.security_wep,
245                         self.security_wpapsk,
246                         self.security_wpa2psk
247
248        @return True if the security mode is supported; False otherwise.
249
250        """
251        return security_mode in self.security
252
253
254    def get_association_parameters(self):
255        """
256        Creates an AssociationParameters from the configured AP.
257
258        @returns AssociationParameters for the configured AP.
259
260        """
261        security_config = None
262        if (ap_spec.SECURITY_TYPE_WPAPSK in self.security or
263            ap_spec.SECURITY_TYPE_WPA2PSK in self.security):
264            # Not all of this is required but doing it just in case.
265            security_config = xmlrpc_security_types.WPAConfig(
266                    psk=self.psk,
267                    wpa_mode=xmlrpc_security_types.WPAConfig.MODE_MIXED_WPA,
268                    wpa_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_CCMP,
269                                 xmlrpc_security_types.WPAConfig.CIPHER_TKIP],
270                    wpa2_ciphers=[xmlrpc_security_types.WPAConfig.CIPHER_CCMP])
271        # TODO(jabele) Allow StaticAPs configured as hidden
272        #              by way of the ap_config file
273        return xmlrpc_datatypes.AssociationParameters(
274                ssid=self._ssid, security_config=security_config,
275                discovery_timeout=45, association_timeout=30,
276                configuration_timeout=30, is_hidden=False)
277