• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2012 The Chromium OS 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 ConfigParser
6import logging
7import os
8import time
9
10from autotest_lib.client.common_lib.cros.network import ap_constants
11from autotest_lib.site_utils.rpm_control_system import rpm_client
12from autotest_lib.server.cros.ap_configurators import ap_spec
13
14# chaos_shadow_ap_list.conf is used for testing against local APs.
15AP_CONFIG_FILES = { ap_constants.AP_TEST_TYPE_CHAOS:
16                    ('chaos_ap_list.conf',
17                     'chaos_shadow_ap_list.conf'),}
18
19TIMEOUT = 100
20
21def get_ap_list(ap_test_type):
22    """
23    Returns the list of AP's from the corresponding configuration file.
24
25    @param ap_test_type: Used to determine which type of test we're
26                         currently running (Chaos vs Clique).
27    @returns a list of AP objects.
28
29    """
30    aps = []
31    ap_config_files = AP_CONFIG_FILES.get(ap_test_type, None)
32    for filename in ap_config_files:
33        ap_config = ConfigParser.RawConfigParser(
34                {AP.CONF_RPM_MANAGED: 'False'})
35        path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
36                            filename)
37        if not os.path.exists(path):
38            logging.warning('Skipping missing config: "%s"', path)
39            continue
40
41        logging.debug('Reading config from: "%s"', path)
42        ap_config.read(path)
43        for bss in ap_config.sections():
44            aps.append(AP(bss, ap_config))
45    return aps
46
47
48class APPowerException(Exception):
49    """ Exception raised when AP fails to power on. """
50    pass
51
52class APSectionError(Exception):
53    """ Exception raised when AP instance does not exist in the config. """
54    pass
55
56class AP(object):
57    """ An instance of an ap defined in the chaos config file.
58
59    This object is a wrapper that can be used to retrieve information
60    about an AP in the chaos lab, and control its power.
61
62    """
63
64
65    # Keys used in the config file.
66    CONF_SSID = 'ssid'
67    CONF_BRAND = 'brand'
68    CONF_MODEL = 'model'
69    CONF_WAN_MAC = 'wan mac'
70    CONF_WAN_HOST = 'wan_hostname'
71    CONF_RPM_MANAGED = 'rpm_managed'
72    CONF_BSS = 'bss'
73    CONF_BSS5 = 'bss5'
74    CONF_BANDWIDTH = 'bandwidth'
75    CONF_SECURITY = 'security'
76    CONF_PSK = 'psk'
77    CONF_FREQUENCY = 'frequency'
78    CONF_BAND = 'band'
79    CONF_CHANNEL = 'channel'
80    CONF_CLASS = 'class_name'
81    CONF_ADMIN = 'admin_url'
82    CONF_ADMIN_IP = 'admin_ip'
83
84
85    def __init__(self, bss, config):
86        """
87        Intialize object
88
89        @param bss: string containing bssid
90        @param config: ConfigParser read from file
91
92        """
93        if not config.has_section(bss):
94            raise APSectionError('BSS (%s) not defined.' % bss)
95        self.bss = bss
96        self.ap_config = config
97
98
99    def get_ssid(self):
100        """@return string ssid for AP from config file"""
101        return self.ap_config.get(self.bss, self.CONF_SSID)
102
103
104    def get_brand(self):
105        """@return string brand for AP from config file"""
106        return self.ap_config.get(self.bss, self.CONF_BRAND)
107
108
109    def get_model(self):
110        """@return string model for AP from config file"""
111        return self.ap_config.get(self.bss, self.CONF_MODEL)
112
113
114    def get_wan_mac(self):
115        """@return string mac for WAN port of AP from config file"""
116        return self.ap_config.get(self.bss, self.CONF_WAN_MAC)
117
118
119    def get_wan_host(self):
120        """@return string host for AP from config file"""
121        return self.ap_config.get(self.bss, self.CONF_WAN_HOST)
122
123
124    def get_rpm_managed(self):
125        """@return bool for AP power via rpm from config file"""
126        return self.ap_config.getboolean(self.bss, self.CONF_RPM_MANAGED)
127
128
129    def get_bss(self):
130        """@return string bss for AP from config file"""
131        try:
132            bss = self.ap_config.get(self.bss, self.CONF_BSS)
133        except ConfigParser.NoOptionError as e:
134            bss = 'N/A'
135        return bss
136
137
138    def get_bss5(self):
139        """@return string bss5 for AP from config file"""
140        try:
141            bss5 = self.ap_config.get(self.bss, self.CONF_BSS5)
142        except ConfigParser.NoOptionError as e:
143            bss5 = 'N/A'
144        return bss5
145
146    def get_bandwidth(self):
147        """@return string bandwidth for AP from config file"""
148        return self.ap_config.get(self.bss, self.CONF_BANDWIDTH)
149
150
151    def get_security(self):
152        """@return string security for AP from config file"""
153        return self.ap_config.get(self.bss, self.CONF_SECURITY)
154
155
156    def get_psk(self):
157        """@return string psk for AP from config file"""
158        return self.ap_config.get(self.bss, self.CONF_PSK)
159
160
161    def get_frequency(self):
162        """@return int frequency for AP from config file"""
163        return int(self.ap_config.get(self.bss, self.CONF_FREQUENCY))
164
165    def get_channel(self):
166        """@return int channel for AP from config file"""
167        return ap_spec.CHANNEL_TABLE[self.get_frequency()]
168
169
170    def get_band(self):
171        """@return string band for AP from config file"""
172        if self.get_frequency() < 4915:
173            return ap_spec.BAND_2GHZ
174        else:
175            return ap_spec.BAND_5GHZ
176
177
178    def get_class(self):
179        """@return string class for AP from config file"""
180        return self.ap_config.get(self.bss, self.CONF_CLASS)
181
182
183    def get_admin(self):
184        """@return string admin for AP from config file"""
185        return self.ap_config.get(self.bss, self.CONF_ADMIN)
186
187
188    def get_admin_ip(self):
189        """@return admin IP for AP from config file"""
190        return self.ap_config.get(self.bss, self.CONF_ADMIN_IP)
191
192
193    def power_off(self):
194        """call rpm_client to power off AP"""
195        rpm_client.set_power_afe(self.get_wan_host(), 'OFF')
196
197
198    def power_on(self):
199        """call rpm_client to power on AP"""
200        rpm_client.set_power_afe(self.get_wan_host(), 'ON')
201
202        # Hard coded timer for now to wait for the AP to come alive
203        # before trying to use it.  We need scanning code
204        # to scan until the AP becomes available (crosbug.com/36710).
205        time.sleep(TIMEOUT)
206
207
208    def __str__(self):
209        """@return string description of AP"""
210        ap_info = {
211            'brand': self.get_brand(),
212            'model': self.get_model(),
213            'ssid' : self.get_ssid(),
214            'bss'  : self.get_bss(),
215            'hostname': self.get_wan_host(),
216        }
217        return ('AP Info:\n'
218                '  Name:      %(brand)s %(model)s\n'
219                '  SSID:      %(ssid)s\n'
220                '  BSS:       %(bss)s\n'
221                '  Hostname:  %(hostname)s\n' % ap_info)
222