Home | History | Annotate | Download | only in networking
      1 # Copyright 2014 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 
      5 import dbus
      6 import dbus.mainloop.glib
      7 import time
      8 
      9 from autotest_lib.client.common_lib.cros.network import apmanager_constants
     10 from autotest_lib.client.cros import dbus_util
     11 
     12 
     13 class ApmanagerProxyError(Exception):
     14     """Exceptions raised by ApmanagerProxy and it's children."""
     15     pass
     16 
     17 
     18 class ApmanagerProxy(object):
     19     """A wrapper around a DBus proxy for apmanager."""
     20 
     21     # Core DBus error names
     22     DBUS_ERROR_UNKNOWN_OBJECT = 'org.freedesktop.DBus.Error.UnknownObject'
     23     DBUS_ERROR_SERVICE_UNKNOWN = 'org.freedesktop.DBus.Error.ServiceUnknown'
     24     DBUS_ERROR_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
     25 
     26     # apmanager Service and Interface names.
     27     DBUS_SERVICE = 'org.chromium.apmanager'
     28     DBUS_PROPERTY_INTERFACE = 'org.freedesktop.DBus.Properties'
     29     DBUS_CONFIG_INTERFACE = 'org.chromium.apmanager.Config'
     30     DBUS_SERVICE_INTERFACE = 'org.chromium.apmanager.Service'
     31     DBUS_MANAGER_INTERFACE = 'org.chromium.apmanager.Manager'
     32     DBUS_MANAGER_PATH = '/org/chromium/apmanager/Manager'
     33 
     34     # AP Service property keys
     35     SERVICE_PROPERTY_CONFIG = 'Config'
     36 
     37     # Mapping for property to dbus type function.
     38     CONFIG_PROPERTY_DBUS_TYPE_MAPPING = {
     39             apmanager_constants.CONFIG_BRIDGE_INTERFACE: dbus.String,
     40             apmanager_constants.CONFIG_CHANNEL: dbus.UInt16,
     41             apmanager_constants.CONFIG_HIDDEN_NETWORK: dbus.Boolean,
     42             apmanager_constants.CONFIG_HW_MODE: dbus.String,
     43             apmanager_constants.CONFIG_INTERFACE_NAME: dbus.String,
     44             apmanager_constants.CONFIG_OPERATION_MODE: dbus.String,
     45             apmanager_constants.CONFIG_PASSPHRASE: dbus.String,
     46             apmanager_constants.CONFIG_SECURITY_MODE: dbus.String,
     47             apmanager_constants.CONFIG_SERVER_ADDRESS_INDEX: dbus.UInt16,
     48             apmanager_constants.CONFIG_SSID: dbus.String}
     49 
     50     POLLING_INTERVAL_SECONDS = 0.2
     51 
     52 
     53     def __init__(self, bus=None, timeout_seconds=10):
     54         if bus is None:
     55             dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
     56             bus = dbus.SystemBus()
     57         self._bus = bus
     58         self._manager = None
     59         self._connect_to_dbus(timeout_seconds)
     60 
     61 
     62     def _connect_to_dbus(self, timeout_seconds):
     63         """Connect to apmanager over DBus and initialize the DBus object for
     64            org.chromium.apmanager.Manager interface.
     65 
     66         If apmanager is not yet running, retry until it is, or until
     67         |timeout_seconds| expires.
     68 
     69         @param timeout_seconds float number of seconds to wait for connecting
     70                to apmanager's DBus service.
     71 
     72         """
     73         end_time = time.time() + timeout_seconds
     74         while self._manager is None and time.time() < end_time:
     75             try:
     76                 self._manager = \
     77                         self._get_dbus_object(self.DBUS_MANAGER_INTERFACE,
     78                                               self.DBUS_MANAGER_PATH)
     79             except dbus.exceptions.DBusException as e:
     80                 if (e.get_dbus_name() !=
     81                     ApmanagerProxy.DBUS_ERROR_SERVICE_UNKNOWN):
     82                     raise ApmanagerProxyError('Error connecting to apmanager')
     83                 else:
     84                     # Wait a moment before retrying
     85                     time.sleep(ApmanagerProxy.POLLING_INTERVAL_SECONDS)
     86         if self._manager is None:
     87             raise ApmanagerProxyError('Timeout connecting to apmanager')
     88 
     89 
     90     def _get_dbus_object(self, interface_name, path):
     91         """Return the DBus object of interface |interface_name| at |path| in
     92            apmanager DBUS service.
     93 
     94         @param interface_name string (e.g. self.DBUS_SERVICE_INTERFACE).
     95         @param path path to object in apmanager (e.g. '/manager/services/1').
     96         @return DBus proxy object.
     97 
     98         """
     99         return dbus.Interface(
    100                 self._bus.get_object(self.DBUS_SERVICE, path),
    101                 interface_name)
    102 
    103 
    104     def _get_dbus_property(self, dbus_object, interface_name, property_key):
    105         """get property on a dbus Interface
    106 
    107         @param dbus_object DBus object to read property from
    108         @param interface_name string name of the interface
    109         @param property_key string name of property on interface
    110         @return python typed object representing property value or None
    111 
    112         """
    113         # Get the property interface for the given DBus object.
    114         property_interface = self._get_dbus_object(
    115                 self.DBUS_PROPERTY_INTERFACE,
    116                 dbus_object.object_path)
    117         # Invoke Get method on the property interface.
    118         try:
    119             value = dbus_util.dbus2primitive(
    120                     property_interface.Get(dbus.String(interface_name),
    121                                            dbus.String(property_key)));
    122         except dbus.exceptions.DBusException as e:
    123             raise ApmanagerProxyError(
    124                     'Failed to get property %s on interface %s' %
    125                     (property_key, interface_name))
    126         return value
    127 
    128 
    129     def _set_dbus_property(self,
    130                            dbus_object,
    131                            interface_name,
    132                            property_key,
    133                            value):
    134         """set property on a dbus Interface
    135 
    136         @param dbus_object DBus object to set property on
    137         @param interface_name string name of the interface
    138         @param property_key string name of property on interface
    139         @param value dbus_type value to set for property
    140 
    141         """
    142         # Get the property interface for the given DBus object.
    143         property_interface = self._get_dbus_object(
    144                 self.DBUS_PROPERTY_INTERFACE,
    145                 dbus_object.object_path)
    146         # Invoke Set method on the property interface.
    147         try:
    148             property_interface.Set(dbus.String(interface_name),
    149                                    dbus.String(property_key),
    150                                    value);
    151         except dbus.exceptions.DBusException as e:
    152             raise ApmanagerProxyError(
    153                     'Failed to set property %s on interface %s' %
    154                     (property_key, interface_name))
    155 
    156 
    157     # TODO(zqiu): add more optional parameters for setting additional
    158     # service configurations.
    159     def start_service(self, config_params):
    160         """Create/start an AP service with provided configurations.
    161 
    162         @param config_params dictionary of configuration parameters.
    163         @return string object path of the newly created service.
    164 
    165         """
    166         service = self._get_dbus_object(
    167                 self.DBUS_SERVICE_INTERFACE,
    168                 dbus_util.dbus2primitive(self._manager.CreateService()))
    169         # Get configuration object for the service.
    170         service_config = self._get_dbus_object(
    171                 self.DBUS_CONFIG_INTERFACE,
    172                 self._get_dbus_property(service,
    173                                         self.DBUS_SERVICE_INTERFACE,
    174                                         self.SERVICE_PROPERTY_CONFIG))
    175         # Set configuration properties.
    176         for name, value in config_params.iteritems():
    177             if name in self.CONFIG_PROPERTY_DBUS_TYPE_MAPPING:
    178                 func = self.CONFIG_PROPERTY_DBUS_TYPE_MAPPING[name]
    179                 self._set_dbus_property(service_config,
    180                                         self.DBUS_CONFIG_INTERFACE,
    181                                         name,
    182                                         func(value, variant_level=1))
    183             else:
    184                 raise ApmanagerProxyError('Unknown configuration parameter [%s]'
    185                                           % name)
    186 
    187         # Start AP service.
    188         service.Start()
    189         return service.object_path
    190 
    191 
    192     def terminate_service(self, service_path):
    193         """ Terminate and remove the AP service |service|.
    194 
    195         @param service_path string object path of the service.
    196 
    197         """
    198         self._manager.RemoveService(dbus.ObjectPath(service_path))
    199