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

Split Close
Expand all
Collapse all
          --- old/cloudinit/sources/DataSourceSmartOS.py
          +++ new/cloudinit/sources/DataSourceSmartOS.py
↓ open down ↓ 286 lines elided ↑ open up ↑
 287  287                  'user_script': user_script,
 288  288                  'operator_script': operator_script,
 289  289                  'per_boot_d': os.path.join(self.paths.get_cpath("scripts"),
 290  290                                             'per-boot'),
 291  291              }
 292  292  
 293  293          self.metadata = util.mergemanydict([md, self.metadata])
 294  294          self.userdata_raw = ud
 295  295          self.vendordata_raw = md['vendor-data']
 296  296          self.network_data = md['network-data']
      297 +        self.routes_data = md['routes']
 297  298  
 298  299          self._set_provisioned()
 299  300          return True
 300  301  
 301  302      def device_name_to_device(self, name):
 302  303          return self.ds_cfg['disk_aliases'].get(name)
 303  304  
 304  305      def get_config_obj(self):
 305  306          if self.smartos_type == SMARTOS_ENV_KVM:
 306  307              return BUILTIN_CLOUD_CONFIG
↓ open down ↓ 3 lines elided ↑ open up ↑
 310  311          return self.metadata['instance-id']
 311  312  
 312  313      @property
 313  314      def network_config(self):
 314  315          if self._network_config is None:
 315  316              if self.network_data is not None:
 316  317                  self._network_config = (
 317  318                      convert_smartos_network_data(
 318  319                          network_data=self.network_data,
 319  320                          dns_servers=self.metadata['dns_servers'],
 320      -                        dns_domain=self.metadata['dns_domain']))
      321 +                        dns_domain=self.metadata['dns_domain'],
      322 +                        routes=self.routes_data))
 321  323          return self._network_config
 322  324  
 323  325  
 324  326  class JoyentMetadataFetchException(Exception):
 325  327      pass
 326  328  
 327  329  
 328  330  class JoyentMetadataTimeoutException(JoyentMetadataFetchException):
 329  331      pass
 330  332  
↓ open down ↓ 451 lines elided ↑ open up ↑
 782  784          system_type = product_name
 783  785  
 784  786      if system_type and 'smartdc' in system_type.lower():
 785  787          return SMARTOS_ENV_KVM
 786  788  
 787  789      return None
 788  790  
 789  791  
 790  792  # Convert SMARTOS 'sdc:nics' data to network_config yaml
 791  793  def convert_smartos_network_data(network_data=None,
 792      -                                 dns_servers=None, dns_domain=None):
      794 +                                 dns_servers=None, dns_domain=None,
      795 +                                 routes=None):
 793  796      """Return a dictionary of network_config by parsing provided
 794  797         SMARTOS sdc:nics configuration data
 795  798  
 796  799      sdc:nics data is a dictionary of properties of a nic and the ip
 797  800      configuration desired.  Additional nic dictionaries are appended
 798  801      to the list.
 799  802  
 800  803      Converting the format is straightforward though it does include
 801  804      duplicate information as well as data which appears to be relevant
 802  805      to the hostOS rather than the guest.
↓ open down ↓ 19 lines elided ↑ open up ↑
 822  825              'address',
 823  826              'broadcast',
 824  827              'dns_nameservers',
 825  828              'dns_search',
 826  829              'metric',
 827  830              'pointopoint',
 828  831              'routes',
 829  832              'scope',
 830  833              'type',
 831  834          ],
      835 +        'route': [
      836 +            'destination',
      837 +            'gateway',
      838 +        ],
 832  839      }
 833  840  
 834  841      if dns_servers:
 835  842          if not isinstance(dns_servers, (list, tuple)):
 836  843              dns_servers = [dns_servers]
 837  844      else:
 838  845          dns_servers = []
 839  846  
 840  847      if dns_domain:
 841  848          if not isinstance(dns_domain, (list, tuple)):
↓ open down ↓ 45 lines elided ↑ open up ↑
 887  894                          gateways = [gw for gw in nic.get('gateways', [])
 888  895                                      if pgws[proto]['match'](gw)]
 889  896                          if len(gateways):
 890  897                              pgws[proto]['gw'] = gateways[0]
 891  898                              subnet.update({'gateway': pgws[proto]['gw']})
 892  899  
 893  900              subnets.append(subnet)
 894  901          cfg.update({'subnets': subnets})
 895  902          config.append(cfg)
 896  903  
      904 +    if routes:
      905 +        for route in routes:
      906 +            cfg = dict((k, v) for k, v in route.items()
      907 +                       if k in valid_keys['route'])
      908 +            # Linux uses the value of 'gateway' to determine automatically if
      909 +            # the route is a forward/next-hop (non-local IP for gateway) or an
      910 +            # interface/resolver (local IP for gateway).  So we can ignore
      911 +            # the 'interface' attribute of sdc:routes, because SDC guarantees
      912 +            # that the gateway is a local IP for "interface=true".
      913 +            cfg.update({
      914 +                'type': 'route',
      915 +                'destination': route['destination'],
      916 +                'gateway': route['gateway']})
      917 +            config.append(cfg)
      918 +
 897  919      if dns_servers:
 898  920          config.append(
 899  921              {'type': 'nameserver', 'address': dns_servers,
 900  922               'search': dns_domain})
 901  923  
 902  924      return {'version': 1, 'config': config}
 903  925  
 904  926  
 905  927  # Used to match classes to dependencies
 906  928  datasources = [
↓ open down ↓ 19 lines elided ↑ open up ↑
 926  948          keys = sys.argv[1:]
 927  949  
 928  950      def load_key(client, key, data):
 929  951          if key in data:
 930  952              return data[key]
 931  953  
 932  954          if key in SMARTOS_ATTRIB_JSON:
 933  955              keyname = SMARTOS_ATTRIB_JSON[key]
 934  956              data[key] = client.get_json(keyname)
 935  957          elif key == "network_config":
 936      -            for depkey in ('network-data', 'dns_servers', 'dns_domain'):
      958 +            for depkey in ('network-data', 'dns_servers', 'dns_domain', 'routes'):
 937  959                  load_key(client, depkey, data)
 938  960              data[key] = convert_smartos_network_data(
 939  961                  network_data=data['network-data'],
 940  962                  dns_servers=data['dns_servers'],
 941      -                dns_domain=data['dns_domain'])
      963 +                dns_domain=data['dns_domain'],
      964 +                routes=data['routes'])
 942  965          else:
 943  966              if key in SMARTOS_ATTRIB_MAP:
 944  967                  keyname, strip = SMARTOS_ATTRIB_MAP[key]
 945  968              else:
 946  969                  keyname, strip = (key, False)
 947  970              data[key] = client.get(keyname, strip=strip)
 948  971  
 949  972          return data[key]
 950  973  
 951  974      data = {}
 952  975      for key in keys:
 953  976          load_key(client=jmc, key=key, data=data)
 954  977  
 955  978      print(json.dumps(data, indent=1, sort_keys=True,
 956  979                       separators=(',', ': ')))
 957  980  
 958  981  # vi: ts=4 expandtab
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX