Merge "conman:  Remove temporary connection_check routes."
diff --git a/conman/interface.py b/conman/interface.py
index 53fe0eb..2d0fbbe 100755
--- a/conman/interface.py
+++ b/conman/interface.py
@@ -17,7 +17,6 @@
 METRIC_5GHZ = 20
 METRIC_24GHZ_5GHZ = 21
 METRIC_24GHZ = 22
-METRIC_TEMPORARY_CONNECTION_CHECK = 99
 
 RFC2385_MULTICAST_ROUTE = '239.0.0.0/8'
 
@@ -83,21 +82,7 @@
                    ' (ACS)' if check_acs else '', self.name)
       return False
 
-    # Temporarily add a route to make sure the connection check can be run.
-    # Give it a high metric so that it won't interfere with normal default
-    # routes.
-    added_temporary_route = False
-    if 'default' not in self.current_routes():
-      logging.debug('Adding temporary connection check routes for dev %s',
-                    self.name)
-      self._ip_route('add', self._gateway_ip,
-                     'dev', self.name,
-                     'metric', str(METRIC_TEMPORARY_CONNECTION_CHECK))
-      self._ip_route('add', 'default',
-                     'via', self._gateway_ip,
-                     'dev', self.name,
-                     'metric', str(METRIC_TEMPORARY_CONNECTION_CHECK))
-      added_temporary_route = True
+    self.add_routes()
 
     cmd = [self.CONNECTION_CHECK, '-I', self.name]
     if check_acs:
@@ -110,17 +95,6 @@
                    self.name,
                    'passed' if result else 'failed')
 
-    # Delete the temporary route.
-    if added_temporary_route:
-      logging.debug('Deleting temporary connection check routes for dev %s',
-                    self.name)
-      self._ip_route('del', 'default',
-                     'dev', self.name,
-                     'metric', str(METRIC_TEMPORARY_CONNECTION_CHECK))
-      self._ip_route('del', self._gateway_ip,
-                     'dev', self.name,
-                     'metric', str(METRIC_TEMPORARY_CONNECTION_CHECK))
-
     return result
 
   def gateway(self):
@@ -147,10 +121,6 @@
       logging.info('Cannot add route for %s without a metric.', self.name)
       return
 
-    if self._gateway_ip is None:
-      logging.info('Cannot add route for %s without a gateway IP.', self.name)
-      return
-
     # If the current routes are the same, there is nothing to do.  If either
     # exists but is different, delete it before adding an updated one.
     current = self.current_routes()
@@ -158,21 +128,28 @@
     to_add = []
 
     subnet = current.get('subnet', {})
-    if (self._subnet and
-        (subnet.get('route', None), subnet.get('metric', None)) !=
-        (self._subnet, str(self.metric))):
-      logging.debug('Adding subnet route for dev %s', self.name)
-      to_add.append(('subnet', ('add', self._subnet, 'dev', self.name,
-                                'metric', str(self.metric))))
-      subnet = self._subnet
+    if self._subnet:
+      if ((subnet.get('route', None), subnet.get('metric', None)) !=
+          (self._subnet, str(self.metric))):
+        logging.debug('Adding subnet route for dev %s', self.name)
+        to_add.append(('subnet', ('add', self._subnet, 'dev', self.name,
+                                  'metric', str(self.metric))))
+        subnet = self._subnet
+    else:
+      subnet = None
+      self.delete_route('default', 'subnet')
 
     default = current.get('default', {})
-    if (subnet and
-        (default.get('via', None), default.get('metric', None)) !=
-        (self._gateway_ip, str(self.metric))):
-      logging.debug('Adding default route for dev %s', self.name)
-      to_add.append(('default', ('add', 'default', 'via', self._gateway_ip,
-                                 'dev', self.name, 'metric', str(self.metric))))
+    if self._gateway_ip:
+      if (subnet and
+          (default.get('via', None), default.get('metric', None)) !=
+          (self._gateway_ip, str(self.metric))):
+        logging.debug('Adding default route for dev %s', self.name)
+        to_add.append(('default',
+                       ('add', 'default', 'via', self._gateway_ip,
+                        'dev', self.name, 'metric', str(self.metric))))
+    else:
+      self.delete_route('default')
 
     # RFC2365 multicast route.
     if current.get('multicast', {}).get('metric', None) != str(self.metric):
@@ -248,17 +225,17 @@
                    ' '.join(self.IP_ROUTE), ' '.join(args))
       return ''
 
-    return self._really_ip_route(*args)
-
-  def _really_ip_route(self, *args):
     try:
       logging.debug('%s calling ip route %s', self.name, ' '.join(args))
-      return subprocess.check_output(self.IP_ROUTE + list(args))
+      return self._really_ip_route(*args)
     except subprocess.CalledProcessError as e:
       logging.error('Failed to call "ip route" with args %r: %s', args,
                     e.message)
       return ''
 
+  def _really_ip_route(self, *args):
+    return subprocess.check_output(self.IP_ROUTE + list(args))
+
   def _ip_addr_show(self):
     try:
       return subprocess.check_output(self.IP_ADDR_SHOW + [self.name])
diff --git a/conman/interface_test.py b/conman/interface_test.py
index 45714a8..79c58ae 100755
--- a/conman/interface_test.py
+++ b/conman/interface_test.py
@@ -7,6 +7,7 @@
 import shutil
 import socket
 import struct
+import subprocess
 import tempfile
 import time
 
@@ -40,6 +41,13 @@
     self.routing_table = {}
     self.ip_testonly = None
 
+  def _connection_check(self, *args, **kwargs):
+    result = super(FakeInterfaceMixin, self)._connection_check(*args, **kwargs)
+    if (self.current_routes().get('default', {}).get('via', None) !=
+        self._gateway_ip):
+      return False
+    return result
+
   def set_connection_check_result(self, result):
     if result in ['succeed', 'fail', 'restricted']:
       # pylint: disable=invalid-name
@@ -87,8 +95,9 @@
     key = (self.name, route, metric)
     if args[0] == 'add' and key not in self.routing_table:
       if not can_add_route():
-        raise ValueError('Tried to add default route without subnet route: %r',
-                         self.routing_table)
+        raise subprocess.CalledProcessError(
+            'Tried to add default route without subnet route: %r',
+            self.routing_table)
       logging.debug('Adding route for %r', key)
       self.routing_table[key] = ' '.join(args[1:])
     elif args[0] == 'del':
@@ -431,8 +440,40 @@
     b.ip_testonly = '192.168.1.100'
     wvtest.WVPASSEQ(b.get_ip_address(), '192.168.1.100')
 
+    # Get a new gateway/subnet (e.g. due to joining a new network).
     # Not on the subnet; adding IP should fail.
-    wvtest.WVEXCEPT(ValueError, b.set_gateway_ip, '192.168.2.1')
+    b.set_gateway_ip('192.168.2.1')
+    wvtest.WVFAIL('default' in b.current_routes())
+    wvtest.WVPASS('subnet' in b.current_routes())
+    # Without a default route, the connection check should fail.
+    wvtest.WVFAIL(b.acs())
+
+    # Now we get the subnet and should add updated subnet and gateway routes.
+    b.set_subnet('192.168.2.0/24')
+    wvtest.WVPASSEQ(b.current_routes()['default']['via'], '192.168.2.1')
+    wvtest.WVPASSLE(int(b.current_routes()['default']['metric']), 50)
+    wvtest.WVPASSEQ(b.current_routes()['subnet']['route'], '192.168.2.0/24')
+    wvtest.WVPASSLE(int(b.current_routes()['subnet']['metric']), 50)
+    wvtest.WVPASS(b.acs())
+
+    # If we have no subnet, make sure that both subnet and default routes are
+    # removed.
+    b.set_subnet(None)
+    wvtest.WVFAIL('subnet' in b.current_routes())
+    wvtest.WVFAIL('default' in b.current_routes())
+
+    # Now repeat the new-network test, but with a faulty connection.  Make sure
+    # the metrics are set appropriately.
+    b.set_connection_check_result('fail')
+    b.set_subnet('192.168.3.0/24')
+    b.set_gateway_ip('192.168.3.1')
+    wvtest.WVPASSGE(int(b.current_routes()['default']['metric']), 50)
+    wvtest.WVPASSGE(int(b.current_routes()['subnet']['metric']), 50)
+
+    # Now test deleting only the gateway IP.
+    b.set_gateway_ip(None)
+    wvtest.WVPASS('subnet' in b.current_routes())
+    wvtest.WVFAIL('default' in b.current_routes())
 
   finally:
     shutil.rmtree(tmp_dir)
@@ -536,6 +577,7 @@
     b = Bridge('br0', '10', acs_autoprovisioning_filepath=autoprov_filepath)
     b.add_moca_station(0)
     b.set_gateway_ip('192.168.1.1')
+    b.set_subnet('192.168.1.0/24')
     b.set_connection_check_result('succeed')
     b.initialize()