Print this page
Handle routes_data better
Handle 'routes' being empty (missing bits)
Handle 'routes' being empty
IMAGE-1097 cloud-init doesn't use sdc:routes metadata

@@ -292,10 +292,11 @@
 
         self.metadata = util.mergemanydict([md, self.metadata])
         self.userdata_raw = ud
         self.vendordata_raw = md['vendor-data']
         self.network_data = md['network-data']
+        self.routes_data = md['routes']
 
         self._set_provisioned()
         return True
 
     def device_name_to_device(self, name):

@@ -315,11 +316,12 @@
             if self.network_data is not None:
                 self._network_config = (
                     convert_smartos_network_data(
                         network_data=self.network_data,
                         dns_servers=self.metadata['dns_servers'],
-                        dns_domain=self.metadata['dns_domain']))
+                        dns_domain=self.metadata['dns_domain'],
+                        routes=self.routes_data))
         return self._network_config
 
 
 class JoyentMetadataFetchException(Exception):
     pass

@@ -787,11 +789,12 @@
     return None
 
 
 # Convert SMARTOS 'sdc:nics' data to network_config yaml
 def convert_smartos_network_data(network_data=None,
-                                 dns_servers=None, dns_domain=None):
+                                 dns_servers=None, dns_domain=None,
+                                 routes=None):
     """Return a dictionary of network_config by parsing provided
        SMARTOS sdc:nics configuration data
 
     sdc:nics data is a dictionary of properties of a nic and the ip
     configuration desired.  Additional nic dictionaries are appended

@@ -827,10 +830,14 @@
             'pointopoint',
             'routes',
             'scope',
             'type',
         ],
+        'route': [
+            'destination',
+            'gateway',
+        ],
     }
 
     if dns_servers:
         if not isinstance(dns_servers, (list, tuple)):
             dns_servers = [dns_servers]

@@ -892,10 +899,25 @@
 
             subnets.append(subnet)
         cfg.update({'subnets': subnets})
         config.append(cfg)
 
+    if routes:
+        for route in routes:
+            cfg = dict((k, v) for k, v in route.items()
+                       if k in valid_keys['route'])
+            # Linux uses the value of 'gateway' to determine automatically if
+            # the route is a forward/next-hop (non-local IP for gateway) or an
+            # interface/resolver (local IP for gateway).  So we can ignore
+            # the 'interface' attribute of sdc:routes, because SDC guarantees
+            # that the gateway is a local IP for "interface=true".
+            cfg.update({
+                'type': 'route',
+                'destination': route['destination'],
+                'gateway': route['gateway']})
+            config.append(cfg)
+
     if dns_servers:
         config.append(
             {'type': 'nameserver', 'address': dns_servers,
              'search': dns_domain})
 

@@ -931,16 +953,17 @@
 
         if key in SMARTOS_ATTRIB_JSON:
             keyname = SMARTOS_ATTRIB_JSON[key]
             data[key] = client.get_json(keyname)
         elif key == "network_config":
-            for depkey in ('network-data', 'dns_servers', 'dns_domain'):
+            for depkey in ('network-data', 'dns_servers', 'dns_domain', 'routes'):
                 load_key(client, depkey, data)
             data[key] = convert_smartos_network_data(
                 network_data=data['network-data'],
                 dns_servers=data['dns_servers'],
-                dns_domain=data['dns_domain'])
+                dns_domain=data['dns_domain'],
+                routes=data['routes'])
         else:
             if key in SMARTOS_ATTRIB_MAP:
                 keyname, strip = SMARTOS_ATTRIB_MAP[key]
             else:
                 keyname, strip = (key, False)