blob: 70d26a752227c1efff425d41b72ec7ac238086c7 [file] [log] [blame]
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import binascii
import copy
import logging
import os
import sys
import web_driver_core_helpers
import web_power_outlet
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'deps',
'chrome_test', 'test_src', 'third_party',
'webdriver', 'pylib'))
try:
from selenium import webdriver
except ImportError:
raise ImportError('Could not locate the webdriver package. Did you build? '
'Are you using a prebuilt autotest package?')
from selenium.common.exceptions import TimeoutException as \
SeleniumTimeoutException
from selenium.webdriver.support.ui import WebDriverWait
class APConfigurator(web_driver_core_helpers.WebDriverCoreHelpers):
"""Base class for objects to configure access points using webdriver."""
def __init__(self, router_dict):
super(APConfigurator, self).__init__()
# Possible bands
self.band_2ghz = '2.4GHz'
self.band_5ghz = '5GHz'
# Possible modes
self.mode_a = 0x0001
self.mode_b = 0x0010
self.mode_g = 0x0100
self.mode_n = 0x1000
# Possible security settings
self.security_disabled = 'Disabled'
self.security_wep = 'WEP'
self.security_wpawpsk = 'WPA-Personal'
self.security_wpa2wpsk = 'WPA2-Personal'
self.security_wpa8021x = 'WPA-Enterprise'
self.security_wpa28021x = 'WPA2-Enterprise'
self.wep_authentication_open = 'Open'
self.wep_authentication_shared = 'Shared Key'
self.admin_interface_url = router_dict['admin_url']
self.class_name = router_dict['class_name']
self.short_name = router_dict['short_name']
self.serial_number = router_dict['serial_number']
self.mac_address = router_dict['mac_address']
self.power_outlet = web_power_outlet.WebPowerOutlet(
router_dict['power_outlet_ip'], router_dict['power_outlet_number'],
router_dict['power_outlet_admin_name'],
router_dict['power_outlet_password'])
self._command_list = []
def __del__(self):
try:
self.driver.close()
except:
pass
def add_item_to_command_list(self, method, args, page, priority):
"""Adds commands to be executed against the AP web UI.
Args:
method: the method to run
args: the arguments for the method you want executed
page: the page on the web ui where the method should be run against
priority: the priority of the method
"""
self._command_list.append({'method': method,
'args': copy.copy(args),
'page': page,
'priority': priority})
def get_router_name(self):
"""Returns a string to describe the router."""
return ('Router name: %s, Controller class: %s, Serial: %s, MAC '
'Address: %s' % (self.short_name, self.class_name,
self.serial_number, self.mac_address))
def get_router_short_name(self):
"""Returns a short string to describe the router."""
return self.short_name
def get_number_of_pages(self):
"""Returns the number of web pages used to configure the router.
Note: This is used internally by apply_settings, and this method must be
implemented by the derived class.
Note: The derived class must implement this method.
"""
raise NotImplementedError
def get_supported_bands(self):
"""Returns a list of dictionaries describing the supported bands.
Example: returned is a dictionary of band and a list of channels. The
band object returned must be one of those defined in the
__init___ of this class.
supported_bands = [{'band' : self.band_2GHz,
'channels' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]},
{'band' : self.band_5ghz,
'channels' : [26, 40, 44, 48, 149, 153, 165]}]
Note: The derived class must implement this method.
Returns:
A list of dictionaries as described above
"""
raise NotImplementedError
def get_supported_modes(self):
"""Returns a list of dictionaries describing the supported modes.
Example: returned is a dictionary of band and a list of modes. The band
and modes objects returned must be one of those defined in the
__init___ of this class.
supported_modes = [{'band' : self.band_2GHz,
'modes' : [mode_b, mode_b | mode_g]},
{'band' : self.band_5ghz,
'modes' : [mode_a, mode_n, mode_a | mode_n]}]
Note: The derived class must implement this method.
Returns:
A list of dictionaries as described above
"""
raise NotImplementedError
def is_security_mode_supported(self, security_mode):
"""Returns if a given security_type is supported.
Note: The derived class must implement this method.
Args:
security_mode: one of the following modes: self.security_disabled,
self.security_wep, self.security_wpapsk,
self.security_wpa2psk, self.security_wpa8021x,
or self.security_wpa28021x
Returns:
True if the security mode provided is supported; False otherwise.
"""
raise NotImplementedError
def navigate_to_page(self, page_number):
"""Navigates to the page corresponding to the given page number.
This method performs the translation between a page number and a url to
load. This is used internally by apply_settings.
Note: The derived class must implement this method.
Args:
page_number: Page number of the page to load
"""
raise NotImplementedError
def power_cycle_router_up(self):
"""Turns the ap off and then back on again."""
self.power_down_router()
self.power_up_router()
def power_down_router(self):
"""Turns off the power to the ap via the power strip."""
self.power_outlet.turn_off_outlet()
def power_up_router(self):
"""Turns on the power to the ap via the power strip.
This method returns once it can navigate to a web page of the ap UI.
"""
self.power_outlet.turn_on_outlet()
self.establish_driver_connection()
self.wait = WebDriverWait(self.driver, timeout=5)
# With the 5 second timeout give the router up to 2 minutes
for i in range(24):
try:
self.navigate_to_page(1)
return
except SeleniumTimeoutException, e:
logging.info('Waiting for router %s to come back up.' %
self.get_router_name)
raise RuntimeError('Unable to load admin page after powering on the '
'router: %s' % self.get_router_name)
def save_page(self, page_number):
"""Saves the given page.
Note: The derived class must implement this method.
Args:
page_number: Page number of the page to save.
"""
raise NotImplementedError
def set_mode(self, mode, band=None):
"""Sets the mode.
Note: The derived class must implement this method.
Args:
mode: must be one of the modes listed in __init__()
band: the band to select
"""
raise NotImplementedError
def set_radio(self, enabled=True):
"""Turns the radio on and off.
Note: The derived class must implement this method.
Args:
enabled: True to turn on the radio; False otherwise
"""
raise NotImplementedError
def set_ssid(self, ssid):
"""Sets the SSID of the wireless network.
Note: The derived class must implement this method.
Args:
ssid: Name of the wireless network
"""
raise NotImplementedError
def set_channel(self, channel):
"""Sets the channel of the wireless network.
Note: The derived class must implement this method.
Args:
channel: Integer value of the channel
"""
raise NotImplementedError
def set_band(self, band):
"""Sets the band of the wireless network.
Currently there are only two possible values for band: 2kGHz and 5kGHz.
Note: The derived class must implement this method.
Args:
band: Constant describing the band type
"""
raise NotImplementedError
def set_security_disabled(self):
"""Disables the security of the wireless network.
Note: The derived class must implement this method.
"""
raise NotImplementedError
def set_security_wep(self, key_value, authentication):
"""Enabled WEP security for the wireless network.
Note: The derived class must implement this method.
Args:
key_value: encryption key to use
authentication: one of two supported authentication types:
wep_authentication_open or wep_authentication_shared
"""
raise NotImplementedError
def set_security_wpapsk(self, shared_key, update_interval=1800):
"""Enabled WPA using a private security key for the wireless network.
Note: The derived class must implement this method.
Args:
shared_key: shared encryption key to use
update_interval: number of seconds to wait before updating
"""
raise NotImplementedError
def set_visibility(self, visible=True):
"""Set the visibility of the wireless network.
Note: The derived class must implement this method.
Args:
visible: True for visible; False otherwise
"""
raise NotImplementedError
def establish_driver_connection(self):
# Load the Auth extension
extension_path = os.path.join(os.path.dirname(__file__),
'basic_auth_extension.crx')
f = open(extension_path, 'rb')
base64_extensions = []
base64_ext = (binascii.b2a_base64(f.read()).strip())
base64_extensions.append(base64_ext)
f.close()
try:
self.driver = webdriver.Remote('http://127.0.0.1:9515',
{'chrome.extensions': base64_extensions})
except Exception, e:
raise RuntimeError('Could not connect to webdriver, have you '
'downloaded the prebuild components to the /tmp '
'directory in the chroot? Have you run: '
'(outside-chroot) <path to chroot tmp directory>'
'/chromium-webdriver-parts/.chromedriver?\n'
'Exception message: %s' % str(e))
def apply_settings(self):
"""Apply all settings to the access point."""
self.establish_driver_connection()
self.wait = WebDriverWait(self.driver, timeout=5)
# Pull items by page and then sort
if self.get_number_of_pages() == -1:
self.fail(msg='Number of pages is not set.')
page_range = range(1, self.get_number_of_pages() + 1)
for i in page_range:
page_commands = [x for x in self._command_list if x['page'] == i]
sorted_page_commands = sorted(page_commands,
key=lambda k: k['priority'])
if sorted_page_commands:
self.navigate_to_page(i)
for command in sorted_page_commands:
command['method'](*command['args'])
self.save_page(i)
self._command_list = []
self.driver.close()