conman: Handle WPACtrl.request errors.
This commit addresses the following problems:
* conman would sometimes call WPACtrl.request when the WPACtrl was not
attached.
* conman didn't catch the wpactrl.error that wpactrl.request may
throw.
* The unit tests would not pass if the system didn't have the real
pywpactrl installed, beacuse the fake wpactrl didn't have the
necessary fake classes. I verified this by removing pywpactrl from
my machine, seeing the tests fail, adding the fake classes, and then
seeing them pass.
BUG=29364078
Change-Id: I04bd94f6c62967d92550335b86e0a33eca44e64c
diff --git a/conman/connection_manager.py b/conman/connection_manager.py
index aa1b320..cbb3b5b 100755
--- a/conman/connection_manager.py
+++ b/conman/connection_manager.py
@@ -95,9 +95,9 @@
@property
def client_up(self):
- wpa_cli_status = self.wifi.wpa_cli_status()
- return (wpa_cli_status.get('wpa_state') == 'COMPLETED'
- and wpa_cli_status.get('ssid') == self.ssid)
+ wpa_status = self.wifi.wpa_status()
+ return (wpa_status.get('wpa_state') == 'COMPLETED'
+ and wpa_status.get('ssid') == self.ssid)
def start_access_point(self):
"""Start an access point."""
diff --git a/conman/interface.py b/conman/interface.py
index d45f42e..f575bf3 100755
--- a/conman/interface.py
+++ b/conman/interface.py
@@ -355,15 +355,15 @@
logging.error('Error attaching to wpa_supplicant: %s', e)
return False
- status = self.wpa_cli_status()
+ status = self.wpa_status()
self.wpa_supplicant = status.get('wpa_state') == 'COMPLETED'
if not self._initialized:
self.initial_ssid = status.get('ssid')
return True
- def wpa_cli_status(self):
- """Parse the STATUS response from the wpa_supplicant CLI.
+ def wpa_status(self):
+ """Parse the STATUS response from the wpa_supplicant control interface.
Returns:
A dict containing the parsed results, where key and value are separated by
@@ -371,8 +371,12 @@
"""
status = {}
- if self._wpa_control:
- lines = self._wpa_control.request('STATUS').splitlines()
+ if self._wpa_control and self._wpa_control.attached:
+ lines = []
+ try:
+ lines = self._wpa_control.request('STATUS').splitlines()
+ except wpactrl.error:
+ logging.error('wpa_control STATUS request failed')
for line in lines:
if '=' not in line:
continue
diff --git a/conman/interface_test.py b/conman/interface_test.py
index 8a376a6..034c5b0 100755
--- a/conman/interface_test.py
+++ b/conman/interface_test.py
@@ -75,6 +75,7 @@
self.attached = False
self.connected = False
self.ssid_testonly = None
+ self.request_status_fails = False
def pending(self):
self.check_socket_exists('pending: socket does not exist')
@@ -97,6 +98,8 @@
def request(self, request_type):
if request_type == 'STATUS':
+ if self.request_status_fails:
+ raise wpactrl.error('test error')
return ('foo\nwpa_state=COMPLETED\nssid=%s\nbar' % self.ssid_testonly
if self.connected else 'foo')
else:
@@ -185,6 +188,7 @@
def __init__(self, *args, **kwargs):
super(FrenzyWPACtrl, self).__init__(*args, **kwargs)
self.ssid_testonly = None
+ self.request_status_fails = False
def _qcsapi(self, *command):
return self.fake_qcsapi.get(command[0], None)
@@ -207,6 +211,12 @@
self.add_terminating_event()
super(FrenzyWPACtrl, self).detach()
+ def request(self, request_type):
+ if request_type == 'STATUS' and self.request_status_fails:
+ raise wpactrl.error('test error')
+
+ return super(FrenzyWPACtrl, self).request(request_type)
+
class FrenzyWifi(FakeInterfaceMixin, interface.FrenzyWifi):
WPACtrl = FrenzyWPACtrl
@@ -366,6 +376,10 @@
w.initialize()
wvtest.WVPASSEQ(w.initial_ssid, None)
+ wvtest.WVPASSNE(w.wpa_status(), {})
+ w._wpa_control.request_status_fails = True
+ wvtest.WVPASSEQ(w.wpa_status(), {})
+
# The wpa_supplicant process disconnects and terminates.
wpa_control.add_disconnected_event()
wpa_control.add_terminating_event()
diff --git a/conman/test/fake_wpactrl/wpactrl/__init__.py b/conman/test/fake_wpactrl/wpactrl/__init__.py
index e69de29..b8ce1fd 100644
--- a/conman/test/fake_wpactrl/wpactrl/__init__.py
+++ b/conman/test/fake_wpactrl/wpactrl/__init__.py
@@ -0,0 +1,5 @@
+class error(Exception):
+ pass
+
+class WPACtrl(object):
+ pass