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