#!/usr/bin/python

"""Manages a device's wired and wireless connections to the LAN."""

import collections
import errno
import glob
import json
import logging
import os
import re
import subprocess
import time

# This is in site-packages on the device, but not when running tests, and so
# raises lint errors.
# pylint: disable=g-bad-import-order
import pyinotify

import cycler
import interface
import iw
import status

GFIBER_OUIS = ['f4:f5:e8']
VENDOR_IE_FEATURE_ID_AUTOPROVISIONING = '01'


class FileChangeHandler(pyinotify.ProcessEvent):
  """Connects pyinotify events to ConnectionManager."""

  def __init__(self, connection_manager, *args, **kwargs):
    self._connection_manager = connection_manager
    super(FileChangeHandler, self).__init__(*args, **kwargs)

  def process_IN_DELETE(self, event):
    self._connection_manager.handle_event(event.path, event.name, True)

  def process_IN_CLOSE_WRITE(self, event):
    self._connection_manager.handle_event(event.path, event.name, False)

  def process_IN_MOVED_TO(self, event):
    self.process_IN_CLOSE_WRITE(event)

  def process_IN_MOVED_FROM(self, event):
    self.process_IN_DELETE(event)

  def check_events(self, *args, **kwargs):
    result = super(FileChangeHandler, self).check_events(*args, **kwargs)
    return result


class WLANConfiguration(object):
  """Represents a WLAN configuration from cwmpd."""

  WIFI_STOPAP = ['wifi', 'stopap', '--persist']
  WIFI_SETCLIENT = ['wifi', 'setclient', '--persist']
  WIFI_STOPCLIENT = ['wifi', 'stopclient', '--persist']

  def __init__(self, band, wifi, command_lines, _status, wpa_control_interface):
    self.band = band
    self.wifi = wifi
    self.command = command_lines.splitlines()
    self.access_point_up = False
    self.ssid = None
    self.passphrase = None
    self.interface_suffix = None
    self.access_point = None
    self._status = _status
    self._wpa_control_interface = wpa_control_interface

    binwifi_option_attrs = {
        '-s': 'ssid',
        '--ssid': 'ssid',
        '-S': 'interface_suffix',
        '--interface_suffix': 'interface_suffix',
    }
    attr = None
    for line in self.command:
      if attr is not None:
        setattr(self, attr, line)
        attr = None
        continue

      attr = binwifi_option_attrs.get(line, None)

      if line.startswith('WIFI_PSK='):
        self.passphrase = line.split('WIFI_PSK=')[-1]

    if self.ssid is None:
      raise ValueError('Command file does not specify SSID')

    if self.wifi.initial_ssid == self.ssid:
      logging.debug('Connected to WLAN at startup')

  @property
  def client_up(self):
    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."""

    if not self.access_point or self.access_point_up:
      return

    # Since we only run an access point if we have a wired connection anyway, we
    # don't want to constrain the AP's channel to the channel of the AP we are
    # connected to.  This line should go away when we have wireless repeaters.
    self.stop_client()

    try:
      subprocess.check_output(self.command, stderr=subprocess.STDOUT)
      self.access_point_up = True
      logging.debug('Started %s GHz AP', self.band)
    except subprocess.CalledProcessError as e:
      logging.error('Failed to start access point: %s', e.output)

  def stop_access_point(self):
    if not self.access_point_up:
      return

    command = self.WIFI_STOPAP + ['--band', self.band]
    if self.interface_suffix:
      command += ['--interface_suffix', self.interface_suffix]

    try:
      subprocess.check_output(command, stderr=subprocess.STDOUT)
      self.access_point_up = False
      logging.debug('Stopped %s GHz AP', self.band)
    except subprocess.CalledProcessError as e:
      logging.error('Failed to stop access point: %s', e.output)
      return

  def start_client(self):
    """Join the WLAN as a client."""
    up = self.client_up
    if up:
      logging.debug('Wifi client already started on %s GHz', self.band)
      return

    command = self.WIFI_SETCLIENT + ['--ssid', self.ssid, '--band', self.band]
    env = dict(os.environ)
    if self.passphrase:
      env['WIFI_CLIENT_PSK'] = self.passphrase
    try:
      self._status.trying_wlan = True
      subprocess.check_output(command, stderr=subprocess.STDOUT, env=env)
    except subprocess.CalledProcessError as e:
      logging.error('Failed to start wifi client: %s', e.output)
      return

    self._status.connected_to_wlan = True
    logging.info('Started wifi client on %s GHz', self.band)
    self.wifi.attach_wpa_control(self._wpa_control_interface)

  def stop_client(self):
    if not self.client_up:
      logging.debug('Wifi client already stopped on %s GHz', self.band)
      return

    self.wifi.detach_wpa_control()

    try:
      subprocess.check_output(self.WIFI_STOPCLIENT + ['-b', self.band],
                              stderr=subprocess.STDOUT)
      # TODO(rofrankel): Make this work for dual-radio devices.
      self._status.connected_to_wlan = False
      logging.debug('Stopped wifi client on %s GHz', self.band)
    except subprocess.CalledProcessError as e:
      logging.error('Failed to stop wifi client: %s', e.output)


class ConnectionManager(object):
  """Manages wired and wireless connections to the LAN."""

  # pylint: disable=invalid-name
  Bridge = interface.Bridge
  Wifi = interface.Wifi
  FrenzyWifi = interface.FrenzyWifi
  WLANConfiguration = WLANConfiguration

  ETHERNET_STATUS_FILE = 'eth0'
  WLAN_FILE_REGEXP_FMT = r'^%s((?P<interface_suffix>.*)\.)?(?P<band>2\.4|5)$'
  COMMAND_FILE_PREFIX = 'command.'
  ACCESS_POINT_FILE_PREFIX = 'access_point.'
  COMMAND_FILE_REGEXP = WLAN_FILE_REGEXP_FMT % COMMAND_FILE_PREFIX
  ACCESS_POINT_FILE_REGEXP = WLAN_FILE_REGEXP_FMT % ACCESS_POINT_FILE_PREFIX
  GATEWAY_FILE_PREFIX = 'gateway.'
  MOCA_NODE_FILE_PREFIX = 'node'
  WIFI_SETCLIENT = ['wifi', 'setclient']
  IFUP = ['ifup']
  IP_LINK = ['ip', 'link']
  IFPLUGD_ACTION = ['/etc/ifplugd/ifplugd.action']
  BINWIFI = ['wifi']

  def __init__(self,
               bridge_interface='br0',
               tmp_dir='/tmp/conman',
               config_dir='/config/conman',
               moca_tmp_dir='/tmp/cwmp/monitoring/moca2',
               wpa_control_interface='/var/run/wpa_supplicant',
               run_duration_s=1, interface_update_period=5,
               wifi_scan_period_s=120, wlan_retry_s=15, acs_update_wait_s=10):

    self._tmp_dir = tmp_dir
    self._config_dir = config_dir
    self._interface_status_dir = os.path.join(tmp_dir, 'interfaces')
    self._status_dir = os.path.join(tmp_dir, 'status')
    self._moca_tmp_dir = moca_tmp_dir
    self._wpa_control_interface = wpa_control_interface
    self._run_duration_s = run_duration_s
    self._interface_update_period = interface_update_period
    self._wifi_scan_period_s = wifi_scan_period_s
    self._wlan_retry_s = wlan_retry_s
    self._acs_update_wait_s = acs_update_wait_s
    self._wlan_configuration = {}

    # Make sure all necessary directories exist.
    for directory in (self._tmp_dir, self._config_dir, self._moca_tmp_dir,
                      self._interface_status_dir, self._moca_tmp_dir):
      if not os.path.exists(directory):
        os.makedirs(directory)
        logging.info('Created monitored directory: %s', directory)

    acs_autoprov_filepath = os.path.join(self._tmp_dir,
                                         'acs_autoprovisioning')
    self.bridge = self.Bridge(
        bridge_interface, '10',
        acs_autoprovisioning_filepath=acs_autoprov_filepath)

    self.create_wifi_interfaces()

    self._status = status.Status(self._status_dir)

    wm = pyinotify.WatchManager()
    wm.add_watch(self._config_dir,
                 pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO |
                 pyinotify.IN_DELETE | pyinotify.IN_MOVED_FROM)
    wm.add_watch(self._tmp_dir,
                 pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO)
    wm.add_watch(self._interface_status_dir,
                 pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO)
    wm.add_watch(self._moca_tmp_dir,
                 pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO)
    self.notifier = pyinotify.Notifier(wm, FileChangeHandler(self), timeout=0)

    # If the ethernet file doesn't exist for any reason when conman starts,
    # check explicitly and run ifplugd.action to create the file.
    if not os.path.exists(os.path.join(self._interface_status_dir, 'eth0')):
      ethernet_up = self.is_interface_up('eth0')
      self.ifplugd_action('eth0', ethernet_up)
      self.bridge.ethernet = ethernet_up

    # Do the same for wifi interfaces , but rather than explicitly setting that
    # the wpa_supplicant link is up, attempt to attach to the wpa_supplicant
    # control interface.
    for wifi in self.wifi:
      if not os.path.exists(
          os.path.join(self._interface_status_dir, wifi.name)):
        wifi_up = self.is_interface_up(wifi.name)
        self.ifplugd_action(wifi.name, wifi_up)
        if wifi_up:
          self._status.attached_to_wpa_supplicant = wifi.attach_wpa_control(
              self._wpa_control_interface)

    for path, prefix in ((self._tmp_dir, self.GATEWAY_FILE_PREFIX),
                         (self._interface_status_dir, ''),
                         (self._moca_tmp_dir, self.MOCA_NODE_FILE_PREFIX),
                         (self._config_dir, self.COMMAND_FILE_PREFIX)):
      for filepath in glob.glob(os.path.join(path, prefix + '*')):
        self._process_file(path, os.path.split(filepath)[-1])

    # Make sure no unwanted APs or clients are running.
    for wifi in self.wifi:
      for band in wifi.bands:
        config = self._wlan_configuration.get(band, None)
        if config:
          if config.access_point:
            # If we have a config and want an AP, we don't want a client.
            self._stop_wifi(band, False, True)
          else:
            # If we have a config but don't want an AP, make sure we aren't
            # running one.
            self._stop_wifi(band, True, False)
          break
      else:
        # If we have no config for this radio, neither a client nor an AP should
        # be running.
        self._stop_wifi(wifi.bands[0], True, True)

    # Now that we've read any existing state, it's okay to let interfaces touch
    # the routing table.
    for ifc in [self.bridge] + self.wifi:
      ifc.initialize()
      logging.debug('%s initialized', ifc.name)

    self._interface_update_counter = 0
    self._try_wlan_after = {'5': 0, '2.4': 0}

  def create_wifi_interfaces(self):
    """Create Wifi interfaces."""

    # If we have multiple client interfaces, 5 GHz-only < both < 2.4 GHz-only.
    def metric_for_bands(bands):
      if '5' in bands:
        if '2.4' in bands:
          return interface.METRIC_24GHZ_5GHZ
        return interface.METRIC_5GHZ
      return interface.METRIC_24GHZ

    def wifi_class(attrs):
      return self.FrenzyWifi if 'frenzy' in attrs else self.Wifi

    self.wifi = sorted([
        wifi_class(attrs)(interface_name,
                          metric_for_bands(attrs['bands']),
                          # Prioritize 5 GHz over 2.4.
                          bands=sorted(attrs['bands'], reverse=True))
        for interface_name, attrs
        in get_client_interfaces().iteritems()
    ], key=lambda w: w.metric)

    for wifi in self.wifi:
      wifi.last_wifi_scan_time = -self._wifi_scan_period_s

  def is_interface_up(self, interface_name):
    """Explicitly check whether an interface is up.

    Only used on startup, and only if ifplugd file is missing.

    Args:
      interface_name:  The name of the interface to check.

    Returns:
      Whether the interface is up.
    """
    try:
      lines = subprocess.check_output(self.IP_LINK).splitlines()
    except subprocess.CalledProcessError as e:
      raise EnvironmentError('Failed to call "ip link": %r', e.message)

    for line in lines:
      if interface_name in line and 'LOWER_UP' in line:
        return True

    return False

  def run(self):
    """Run the main loop, and clean up when done."""
    try:
      while True:
        self.run_once()
    finally:
      for wifi in self.wifi:
        wifi.detach_wpa_control()
      self.notifier.stop()

  def run_once(self):
    """Run one iteration of the main loop.

    This includes the following:

    1. Process any changes in watched files.
    2. Check interfaces for changed connectivity, if
       update_interfaces_and_routes is true.
    3. Start, stop, or restart access points as appropriate.  If running an
       access point, skip all remaining wifi steps for that band.
    3. Handle any wpa_supplicant events.
    4. Periodically, perform a wifi scan.
    5. If not connected to the WLAN or to the ACS, try to connect to something.
    6. If connected to the ACS but not the WLAN, and enough time has passed
       since connecting that we should expect a current WLAN configuration, try
       to join the WLAN again.
    7. Sleep for the rest of the duration of _run_duration_s.
    """
    start_time = time.time()
    self.notifier.process_events()
    while self.notifier.check_events():
      self.notifier.read_events()
      self.notifier.process_events()

    self._interface_update_counter += 1
    if self._interface_update_counter == self._interface_update_period:
      self._interface_update_counter = 0
      self._update_interfaces_and_routes()

    for wifi in self.wifi:
      continue_wifi = False

      # Only one wlan_configuration per interface will have access_point ==
      # True.  Try 5 GHz first, then 2.4 GHz.  If both bands are supported by
      # the same radio, and the enabled band is changed, then hostapd will be
      # updated by the wifi command, but we should tell any other
      # wlan_configurations that their APs have been disabled.
      for band in wifi.bands:
        wlan_configuration = self._wlan_configuration.get(band, None)
        if continue_wifi:
          if wlan_configuration:
            wlan_configuration.access_point_up = False
          continue

        # Make sure access point is running iff it should be.
        if wlan_configuration:
          self._update_access_point(wlan_configuration)
          # If we are running an AP on this interface, we don't want to make any
          # client connections on it.
          if wlan_configuration.access_point_up:
            continue_wifi = True

      if not wifi.attached():
        logging.debug('Attempting to attach to wpa control interface for %s',
                      wifi.name)
        self._status.attached_to_wpa_supplicant = wifi.attach_wpa_control(
            self._wpa_control_interface)
      wifi.handle_wpa_events()

      if continue_wifi:
        logging.debug('Running AP on %s, nothing else to do.', wifi.name)
        continue

      # If this interface is connected to the user's WLAN, there is nothing else
      # to do.
      if self._connected_to_wlan(wifi):
        self._status.connected_to_wlan = True
        logging.debug('Connected to WLAN on %s, nothing else to do.', wifi.name)
        return

      # This interface is not connected to the WLAN, so scan for potential
      # routes to the ACS for provisioning.
      if (not self.acs() and
          not getattr(wifi, 'last_successful_bss_info', None) and
          time.time() > wifi.last_wifi_scan_time + self._wifi_scan_period_s):
        logging.debug('Performing scan on %s.', wifi.name)
        self._wifi_scan(wifi)

      # Periodically retry rejoining the WLAN.  If the WLAN configuration is
      # updated then _update_wlan_configuration will do this immediately, but
      # maybe the credentials didn't change and we were just waiting for the AP
      # to restart or something.  Try both bands, so we can fall back to 2.4 in
      # case 5 is unavailable for some reason.
      for band in wifi.bands:
        wlan_configuration = self._wlan_configuration.get(band, None)
        if wlan_configuration and time.time() > self._try_wlan_after[band]:
          logging.debug('Trying to join WLAN on %s.', wifi.name)
          wlan_configuration.start_client()
          if self._connected_to_wlan(wifi):
            logging.debug('Joined WLAN on %s.', wifi.name)
            self._status.connected_to_wlan = True
            self._try_wlan_after[band] = 0
            break
          else:
            logging.error('Failed to connect to WLAN on %s.', wifi.name)
            self._status.connected_to_wlan = False
            self._try_wlan_after[band] = time.time() + self._wlan_retry_s
      else:
        # If we are aren't on the WLAN, can ping the ACS, and haven't gotten a
        # new WLAN configuration yet, there are two possibilities:
        #
        # 1) The configuration didn't change, and we should retry connecting.
        # 2) cwmpd isn't writing a configuration, possibly because the device
        #    isn't registered to any accounts.
        logging.debug('Unable to join WLAN on %s', wifi.name)
        self._status.connected_to_wlan = False
        if self.acs():
          logging.debug('Connected to ACS on %s', wifi.name)
          wifi.last_successful_bss_info = getattr(wifi,
                                                  'last_attempted_bss_info',
                                                  None)
          now = time.time()
          if (self._wlan_configuration and
              hasattr(wifi, 'waiting_for_acs_since')):
            if now - wifi.waiting_for_acs_since > self._acs_update_wait_s:
              logging.info('ACS has not updated WLAN configuration; will retry '
                           ' with old config.')
              for w in self.wifi:
                for b in w.bands:
                  self._try_wlan_after[b] = now
              continue
          # We don't want to want to log this spammily, so do exponential
          # backoff.
          elif (hasattr(wifi, 'complain_about_acs_at')
                and now >= wifi.complain_about_acs_at):
            wait = wifi.complain_about_acs_at - wifi.waiting_for_acs_since
            logging.info('Can ping ACS, but no WLAN configuration for %ds.',
                         wait)
            wifi.complain_about_acs_at += wait
        # If we didn't manage to join the WLAN and we don't have an ACS
        # connection, we should try to establish one.
        else:
          logging.debug('Not connected to ACS on %s', wifi.name)
          self._try_next_bssid(wifi)

    time.sleep(max(0, self._run_duration_s - (time.time() - start_time)))

  def acs(self):
    result = self.bridge.acs() or any(wifi.acs() for wifi in self.wifi)
    self._status.can_reach_acs = result
    return result

  def internet(self):
    result = self.bridge.internet() or any(wifi.internet()
                                           for wifi in self.wifi)
    self._status.can_reach_internet = result
    return result

  def _update_interfaces_and_routes(self):
    """Touch each interface via update_routes."""

    self.bridge.update_routes()
    for wifi in self.wifi:
      wifi.update_routes()
      # If wifi is connected to something that's not the WLAN, it must be a
      # provisioning attempt, and in particular that attempt must be via
      # last_attempted_bss_info.  If that is the same as the
      # last_successful_bss_info (i.e. the last attempt was successful) and we
      # aren't connected to the ACS after calling update_routes (which expires
      # the connection status cache), then this BSS is no longer successful.
      if (wifi.wpa_supplicant and
          not self._connected_to_wlan(wifi) and
          (getattr(wifi, 'last_successful_bss_info', None) ==
           getattr(wifi, 'last_attempted_bss_info', None)) and
          not wifi.acs()):
        wifi.last_successful_bss_info = None

    # Make sure these get called semi-regularly so that exported status is up-
    # to-date.
    self.acs()
    self.internet()

  def handle_event(self, path, filename, deleted):
    if deleted:
      self._handle_deleted_file(path, filename)
    else:
      self._process_file(path, filename)

  def _handle_deleted_file(self, path, filename):
    if path == self._config_dir:
      match = re.match(self.COMMAND_FILE_REGEXP, filename)
      if match:
        band = match.group('band')
        if band in self._wlan_configuration:
          self._remove_wlan_configuration(band)
          return

      match = re.match(self.ACCESS_POINT_FILE_REGEXP, filename)
      if match:
        band = match.group('band')
        if band in self._wlan_configuration:
          self._wlan_configuration[band].access_point = False
          return

  def _remove_wlan_configuration(self, band):
    config = self._wlan_configuration[band]
    config.stop_client()
    config.stop_access_point()
    del self._wlan_configuration[band]
    if not self._wlan_configuration:
      self._status.have_config = False

  def _process_file(self, path, filename):
    """Process or ignore an updated file in a watched directory."""
    filepath = os.path.join(path, filename)
    try:
      contents = open(filepath).read().strip()
    except IOError as e:
      if e.errno == errno.ENOENT:
        # Logging about failing to open .tmp files results in spammy logs.
        if not filename.endswith('.tmp'):
          logging.error('Not a file: %s', filepath)
        return
      else:
        raise

    if path == self._interface_status_dir:
      if filename == self.ETHERNET_STATUS_FILE:
        try:
          self.bridge.ethernet = bool(int(contents))
          logging.debug('Ethernet %s', 'up' if self.bridge.ethernet else 'down')
        except ValueError:
          logging.error('Status file contents should be 0 or 1, not %s',
                        contents)
          return

    elif path == self._config_dir:
      if filename.startswith(self.COMMAND_FILE_PREFIX):
        match = re.match(self.COMMAND_FILE_REGEXP, filename)
        if match:
          band = match.group('band')
          wifi = self.wifi_for_band(band)
          if wifi:
            self._update_wlan_configuration(
                self.WLANConfiguration(band, wifi, contents, self._status,
                                       self._wpa_control_interface))
      elif filename.startswith(self.ACCESS_POINT_FILE_PREFIX):
        match = re.match(self.ACCESS_POINT_FILE_REGEXP, filename)
        if match:
          band = match.group('band')
          wifi = self.wifi_for_band(band)
          if wifi and band in self._wlan_configuration:
            self._wlan_configuration[band].access_point = True
          logging.debug('AP enabled for %s GHz', band)

    elif path == self._tmp_dir:
      if filename.startswith(self.GATEWAY_FILE_PREFIX):
        interface_name = filename.split(self.GATEWAY_FILE_PREFIX)[-1]
        ifc = self.interface_by_name(interface_name)
        if ifc:
          ifc.set_gateway_ip(contents)
          logging.debug('Received gateway %r for interface %s', contents,
                        ifc.name)

    elif path == self._moca_tmp_dir:
      match = re.match(r'^%s\d+$' % self.MOCA_NODE_FILE_PREFIX, filename)
      if match:
        try:
          json_contents = json.loads(contents)
        except ValueError:
          logging.error('Cannot parse %s as JSON.', filepath)
          return
        node = json_contents['NodeId']
        had_moca = self.bridge.moca
        if json_contents.get('RxNBAS', 0) == 0:
          self.bridge.remove_moca_station(node)
        else:
          self.bridge.add_moca_station(node)
        has_moca = self.bridge.moca
        if had_moca != has_moca:
          self.ifplugd_action('moca0', has_moca)

  def interface_by_name(self, interface_name):
    for ifc in [self.bridge] + self.wifi:
      if ifc.name == interface_name:
        return ifc

  def wifi_for_band(self, band):
    for wifi in self.wifi:
      if band in wifi.bands:
        return wifi

    logging.error('No wifi interface for %s GHz.  wlan interfaces:\n%s',
                  band, '\n'.join('%s: %r' %
                                  (w.name, w.bands) for w in self.wifi))

  def ifplugd_action(self, interface_name, up):
    subprocess.call(self.IFPLUGD_ACTION + [interface_name,
                                           'up' if up else 'down'])

  def _wifi_scan(self, wifi):
    """Perform a wifi scan and update wifi.cycler."""
    logging.info('Scanning on %s...', wifi.name)
    wifi.last_wifi_scan_time = time.time()
    subprocess.call(self.IFUP + [wifi.name])
    # /bin/wifi takes a --band option but then finds the right interface for it,
    # so it's okay to just pick the first band here.
    with_ie, without_ie = self._find_bssids(wifi.bands[0])
    logging.info('Done scanning on %s', wifi.name)
    items = [(bss_info, 3) for bss_info in with_ie]
    items += [(bss_info, 1) for bss_info in without_ie]
    wifi.cycler = cycler.AgingPriorityCycler(cycle_length_s=30, items=items)

  def _find_bssids(self, band):
    def supports_autoprovisioning(oui, vendor_ie):
      if oui not in GFIBER_OUIS:
        return False

      return vendor_ie.startswith(VENDOR_IE_FEATURE_ID_AUTOPROVISIONING)

    return iw.find_bssids(band, supports_autoprovisioning, False)

  def _try_next_bssid(self, wifi):
    """Attempt to connect to the next BSSID in wifi's BSSID cycler.

    Args:
      wifi: The wifi interface to use.

    Returns:
      Whether connecting to the network succeeded.
    """
    if not hasattr(wifi, 'cycler'):
      return False

    last_successful_bss_info = getattr(wifi, 'last_successful_bss_info', None)
    bss_info = last_successful_bss_info or wifi.cycler.next()
    if bss_info is not None:
      logging.debug('Attempting to connect to SSID %s for provisioning',
                    bss_info.ssid)
      self._status.trying_open = True
      connected = self._try_bssid(wifi, bss_info)
      if connected:
        self._status.connected_to_open = True
        now = time.time()
        wifi.waiting_for_acs_since = now
        wifi.complain_about_acs_at = now + 5
        logging.info('Attempting to provision via SSID %s', bss_info.ssid)
      # If we can no longer connect to this, it's no longer successful.
      elif bss_info == last_successful_bss_info:
        wifi.last_successful_bss_info = None
      return connected
    else:
      # TODO(rofrankel):  There are probably more cases in which this should be
      # true, e.g. if we keep trying the same few unsuccessful BSSIDs.
      # Relatedly, once we find ACS access on an open network we may want to
      # save that SSID/BSSID and that first in future.  If we do that then we
      # can declare that provisioning has failed much more aggressively.
      self._status.provisioning_failed = True

    return False

  def _try_bssid(self, wifi, bss_info):
    wifi.last_attempted_bss_info = bss_info
    return subprocess.call(self.WIFI_SETCLIENT +
                           ['--ssid', bss_info.ssid,
                            '--band', wifi.bands[0],
                            '--bssid', bss_info.bssid]) == 0

  def _connected_to_wlan(self, wifi):
    return (wifi.wpa_supplicant and
            any(config.client_up for band, config
                in self._wlan_configuration.iteritems()
                if band in wifi.bands))

  def _update_wlan_configuration(self, wlan_configuration):
    band = wlan_configuration.band
    current = self._wlan_configuration.get(band, None)
    if current is None or wlan_configuration.command != current.command:
      if current is not None:
        wlan_configuration.access_point = current.access_point
      else:
        ap_file = os.path.join(
            self._config_dir, self.ACCESS_POINT_FILE_PREFIX +
            (('%s.' % wlan_configuration.interface_suffix)
             if wlan_configuration.interface_suffix else '') + band)
        wlan_configuration.access_point = os.path.exists(ap_file)
      self._wlan_configuration[band] = wlan_configuration
      self._status.have_config = True
      logging.debug('Updated WLAN configuration for %s GHz', band)
      self._update_access_point(wlan_configuration)

  def _update_access_point(self, wlan_configuration):
    if self.bridge.internet() and wlan_configuration.access_point:
      wlan_configuration.start_access_point()
    else:
      wlan_configuration.stop_access_point()
      wlan_configuration.start_client()

  def _stop_wifi(self, band, stopap, stopclient):
    """Stop running wifi processes.

    At least one of [stopap, stopclient] must be True.

    Args:
      band:  The band on which to stop wifi.
      stopap:  Whether to stop access points.
      stopclient:  Whether to stop wifi clients.

    Raises:
      ValueError:  If neither stopap nor stopclient is True.
    """
    if stopap and stopclient:
      command = 'stop'
    elif stopap:
      command = 'stopap'
    elif stopclient:
      command = 'stopclient'
    else:
      raise ValueError('Called _stop_wifi without specifying AP or client.')

    full_command = [command, '--band', band, '--persist']

    try:
      self._binwifi(*full_command)
    except subprocess.CalledProcessError as e:
      logging.error('wifi %s failed: "%s"', ' '.join(full_command), e.output)

  def _binwifi(self, *command):
    """Test seam for calls to /bin/wifi.

    Only used by _stop_wifi, and probably shouldn't be used by anything else.

    Args:
      *command:  A command for /bin/wifi

    Raises:
      subprocess.CalledProcessError:  If the command fails.  Deliberately not
      handled here to make future authors think twice before using this.
    """
    subprocess.check_output(self.BINWIFI + list(command),
                            stderr=subprocess.STDOUT)


def _wifi_show():
  try:
    return subprocess.check_output(['wifi', 'show'])
  except subprocess.CalledProcessError as e:
    logging.error('Failed to call "wifi show": %s', e)
    return ''


def _get_quantenna_interfaces():
  try:
    return subprocess.check_output(['get-quantenna-interfaces']).split()
  except subprocess.CalledProcessError:
    logging.fatal('Failed to call get-quantenna-interfaces')
    raise


def get_client_interfaces():
  """Find all client interfaces on the device.

  Returns:
    A dict mapping wireless client interfaces to their supported bands.
  """
  # TODO(mikemu): Use wifi_files instead of "wifi show".

  current_band = None
  result = collections.defaultdict(lambda: collections.defaultdict(set))
  for line in _wifi_show().splitlines():
    if line.startswith('Band:'):
      current_band = line.split()[1]
    elif line.startswith('Client Interface:'):
      result[line.split()[2]]['bands'].add(current_band)

  for quantenna_interface in _get_quantenna_interfaces():
    if quantenna_interface.startswith('wcli'):
      result[quantenna_interface]['bands'].add('5')
      result[quantenna_interface]['frenzy'] = True

  return result
