• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import dbus
6import dbus.mainloop.glib
7import time
8
9from autotest_lib.client.common_lib.cros.network import apmanager_constants
10from autotest_lib.client.cros import dbus_util
11
12
13class ApmanagerProxyError(Exception):
14    """Exceptions raised by ApmanagerProxy and it's children."""
15    pass
16
17
18class 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