| # Copyright (c) 2012 The Chromium OS 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 dbus |
| import httplib |
| import os |
| import re |
| import subprocess |
| import sys |
| import time |
| |
| from autotest_lib.client.cros import flimflam_test_path |
| import flimflam |
| |
| _CONNECTION_TIMEOUT_SEC = 15.0 |
| _PING_TIMEOUT_SEC = 15 |
| _SLEEP_INTERVAL_SEC = 0.5 |
| |
| _UNKNOWN_PROC = 'unknown' |
| _DEFAULT_MANAGER = 'flimflam' |
| _DEFAULT_PROC_NAME = _UNKNOWN_PROC |
| _MANAGER_LIST = ['flimflam', 'shill'] |
| _PROC_NAME_LIST = [_UNKNOWN_PROC, 'flimflamd', 'shill'] |
| |
| |
| class ConnectionManagerException(Exception): |
| pass |
| |
| |
| class WLAN(object): |
| '''Class for wireless network settings.''' |
| def __init__(self, ssid, security, passphrase): |
| ''' Constructor. |
| |
| Please see 'http://code.google.com/searchframe#wZuuyuB8jKQ/src/third_party/ |
| flimflam/doc/service-api.txt' for a detailed explanation of these |
| parameters. |
| |
| Args: |
| ssid: Wireless network SSID. |
| security: Wireless network security type. |
| passphrase: Wireless network password. |
| ''' |
| self.ssid = ssid |
| self.security = security |
| self.passphrase = passphrase |
| |
| |
| class ConnectionManager(): |
| |
| def __init__(self, wlans=None, |
| network_manager=_DEFAULT_MANAGER, |
| process_name=_DEFAULT_PROC_NAME): |
| '''Constructor. |
| |
| Args: |
| wlans: A list of preferred wireless networks and their properties. |
| Each item should be a WLAN object. |
| network_manager: The name of the network manager in initctl. It |
| should be either flimflam(old) or shill(new). |
| process_name: The name of the network manager process, which should be |
| flimflamd or shill. If you are not sure about it, you can |
| use _UNKNOWN_PROC to let the class auto-detect it. |
| ''' |
| # Black hole for those useless outputs. |
| self.fnull = open(os.devnull, 'w') |
| |
| assert network_manager in _MANAGER_LIST |
| assert process_name in _PROC_NAME_LIST |
| self.network_manager = network_manager |
| self.process_name = process_name |
| # Auto-detect the network manager process name if unknown. |
| if self.process_name == _UNKNOWN_PROC: |
| self._DetectProcName() |
| if wlans is None: |
| wlans = [] |
| self._ConfigureWifi(wlans) |
| |
| # Start network manager to get device info. |
| self.EnableNetworking() |
| self._GetDeviceInfo() |
| self.DisableNetworking() |
| |
| def _DetectProcName(self): |
| '''Detects the network manager process with pgrep.''' |
| for process_name in _PROC_NAME_LIST[1:]: |
| if not subprocess.call("pgrep %s" % process_name, |
| shell=True, stdout=self.fnull): |
| self.process_name = process_name |
| return |
| raise ConnectionManagerException("Can't find the network manager process") |
| |
| def _GetDeviceInfo(self): |
| '''Gets hardware properties of all network devices.''' |
| flim = flimflam.FlimFlam() |
| self.device_list = [dev.GetProperties(utf8_strings=True) |
| for dev in flim.GetObjectList("Device")] |
| |
| def _ConfigureWifi(self, wlans): |
| '''Configures the wireless network settings. |
| |
| The setting will let the network manager auto-connect the preferred |
| wireless networks. |
| |
| Args: |
| wlans: A list of preferred wireless networks and their properties. |
| Each item should be a WLAN object. |
| ''' |
| self.wlans = [] |
| for wlan in wlans: |
| self.wlans.append({ |
| 'Type': 'wifi', |
| 'Mode': 'managed', |
| 'AutoConnect': True, |
| 'SSID': wlan.ssid, |
| 'Security': wlan.security, |
| 'Passphrase': wlan.passphrase |
| }) |
| |
| def EnableNetworking(self): |
| '''Tells underlying connection manager to try auto-connecting.''' |
| # Start network manager. |
| subprocess.call("start %s" % self.network_manager, shell=True, |
| stdout=self.fnull, stderr=self.fnull) |
| |
| # Configure the network manager to auto-connect wireless networks. |
| flim = flimflam.FlimFlam() |
| for wlan in self.wlans: |
| flim.manager.ConfigureService(wlan) |
| |
| def DisableNetworking(self): |
| '''Tells underlying connection manager to terminate any existing connection. |
| ''' |
| # Stop network manager. |
| subprocess.call("stop %s" % self.network_manager, shell=True, |
| stdout=self.fnull, stderr=self.fnull) |
| |
| # Turn down drivers for interfaces to really stop the network. |
| for dev in self.device_list: |
| subprocess.call("ifconfig %s down" % dev['Interface'], |
| shell=True, stdout=self.fnull, stderr=self.fnull) |
| |
| def CheckHost(self, host, timeout=_PING_TIMEOUT_SEC): |
| '''Checks if we can reach a host. |
| |
| Args: |
| host: The host address. |
| timeout: Timeout in seconds. Integers only. |
| |
| Returns: |
| True if host is successfully pinged. |
| ''' |
| if subprocess.call("ping %s -c 1 -w %d" % (host, int(timeout)), shell=True, |
| stdout=self.fnull, stderr=self.fnull): |
| return False |
| return True |
| |
| def WaitForConnection(self, timeout=_CONNECTION_TIMEOUT_SEC): |
| '''A blocking function that waits until any network is connected. |
| |
| The function will raise an Exception if no network is ready when |
| the time runs out. |
| |
| Args: |
| timeout: Timeout in seconds. |
| ''' |
| t_start = time.clock() |
| while not self.IsConnected(): |
| if time.clock() - t_start > timeout: |
| raise ConnectionManagerException('Not connected') |
| time.sleep(_SLEEP_INTERVAL_SEC) |
| |
| def IsConnected(self): |
| '''Returns (network state == online).''' |
| # Check if we are connected to any network. |
| # We can't cache the flimflam object because each time we re-start |
| # the network some filepaths that flimflam works on will change. |
| try: |
| flim = flimflam.FlimFlam() |
| except dbus.exceptions.DBusException: |
| # The network manager is not running. |
| return False |
| |
| stat = flim.GetSystemState() |
| return stat != 'offline' |