| === modified file 'cloudinit/sources/DataSourceConfigDrive.py' | |
| --- cloudinit/sources/DataSourceConfigDrive.py 2016-05-19 22:33:15 +0000 | |
| +++ cloudinit/sources/DataSourceConfigDrive.py 2016-05-25 22:49:19 +0000 | |
| @@ -137,6 +137,7 @@ | |
| self.ec2_metadata = results.get('ec2-metadata') | |
| self.userdata_raw = results.get('userdata') | |
| self.version = results['version'] | |
| + self.osversion = results.get('osversion') | |
| self.files.update(results.get('files', {})) | |
| vd = results.get('vendordata') | |
| @@ -163,8 +164,10 @@ | |
| def network_config(self): | |
| if self._network_config is None: | |
| if self.network_json is not None: | |
| - self._network_config = openstack.convert_net_json( | |
| - self.network_json) | |
| + reader = openstack.NetJsonReader() | |
| + network_config = reader.read(self.network_json, | |
| + osversion=self.osversion) | |
| + self._network_config = network_config | |
| return self._network_config | |
| === modified file 'cloudinit/sources/helpers/openstack.py' | |
| --- cloudinit/sources/helpers/openstack.py 2016-05-19 21:26:30 +0000 | |
| +++ cloudinit/sources/helpers/openstack.py 2016-05-25 22:47:57 +0000 | |
| @@ -242,7 +242,9 @@ | |
| 'userdata': '', | |
| 'version': 2, | |
| } | |
| - data = datafiles(self._find_working_version()) | |
| + os_version = self._find_working_version() | |
| + results['osversion'] = os_version | |
| + data = datafiles(os_version) | |
| for (name, (path, required, translator)) in data.items(): | |
| path = self._path_join(self.base_path, path) | |
| data = None | |
| @@ -474,22 +476,22 @@ | |
| retries=self.retries) | |
| -def convert_net_json(network_json): | |
| - """Return a dictionary of network_config by parsing provided | |
| - OpenStack ConfigDrive NetworkData json format | |
| - | |
| - OpenStack network_data.json provides a 3 element dictionary | |
| - - "links" (links are network devices, physical or virtual) | |
| - - "networks" (networks are ip network configurations for one or more | |
| - links) | |
| - - services (non-ip services, like dns) | |
| - | |
| - networks and links are combined via network items referencing specific | |
| - links via a 'link_id' which maps to a links 'id' field. | |
| - | |
| - To convert this format to network_config yaml, we first iterate over the | |
| - links and then walk the network list to determine if any of the networks | |
| - utilize the current link; if so we generate a subnet entry for the device | |
| +class NetJsonReader(object): | |
| + """Reader that understands how to convert openstack format to our format. | |
| + | |
| + OpenStack ``network_data.json`` provides a 3 element dictionary: | |
| + | |
| + - "links" (links are network devices, physical or virtual) | |
| + - "networks" (networks are ip network configurations for one or more links) | |
| + - services (non-ip services, like dns) | |
| + | |
| + ``networks`` and ``links`` are combined via network items referencing | |
| + specific links via a 'link_id' which maps to a links 'id' field. | |
| + | |
| + To convert this format to ``network_config`` yaml, we first iterate over | |
| + the links and then walk the network list to determine if any of the | |
| + networks utilize the current link; if so we generate a subnet entry for | |
| + the device | |
| We also need to map network_data.json fields to network_config fields. For | |
| example, the network_data links 'id' field is equivalent to network_config | |
| @@ -527,76 +529,102 @@ | |
| ], | |
| } | |
| - links = network_json.get('links', []) | |
| - networks = network_json.get('networks', []) | |
| - services = network_json.get('services', []) | |
| - | |
| - config = [] | |
| - for link in links: | |
| - subnets = [] | |
| - cfg = dict((k, v) for k, v in link.items() | |
| - if k in valid_keys['physical']) | |
| - cfg.update({'name': link['id']}) | |
| - for network in [net for net in networks | |
| - if net['link'] == link['id']]: | |
| - subnet = dict((k, v) for k, v in network.items() | |
| - if k in valid_keys['subnet']) | |
| - if 'dhcp' in network['type']: | |
| - t = 'dhcp6' if network['type'].startswith('ipv6') else 'dhcp4' | |
| - subnet.update({ | |
| - 'type': t, | |
| - }) | |
| + def _fixup_2015_10_15(self, network_json): | |
| + fixed_links = [] | |
| + fixed = False | |
| + for link in network_json.get('links', []): | |
| + # See: http://lists.openstack.org/pipermail/openstack-dev/\ | |
| + # 2016-May/thread.html#95835 | |
| + if link['type'] in ['ethernet', 'vif', 'ovs', 'bridge']: | |
| + link = copy.deepcopy(link) | |
| + link['type'] = 'phy' | |
| + fixed = True | |
| + fixed_links.append(link) | |
| + if fixed: | |
| + network_json = copy.deepcopy(network_json) | |
| + network_json['links'] = fixed_links | |
| + return network_json | |
| + | |
| + def _fixup_latest(self, network_json): | |
| + # Until ML bug(?) is fixed... | |
| + return self._fixup_2015_10_15(network_json) | |
| + | |
| + def read(self, network_json, osversion=None): | |
| + if osversion: | |
| + osversion = osversion.replace("-", "_") | |
| + try: | |
| + fixer_func = getattr(self, "_fixup_%s" % osversion) | |
| + except AttributeError: | |
| + pass | |
| else: | |
| - subnet.update({ | |
| - 'type': 'static', | |
| - 'address': network.get('ip_address'), | |
| - }) | |
| - if network['type'] == 'ipv6': | |
| - subnet['ipv6'] = True | |
| + network_json = fixer_func(network_json) | |
| + | |
| + links = network_json.get('links', []) | |
| + networks = network_json.get('networks', []) | |
| + services = network_json.get('services', []) | |
| + | |
| + config = [] | |
| + for link in links: | |
| + subnets = [] | |
| + cfg = dict((k, v) for k, v in link.items() | |
| + if k in valid_keys['physical']) | |
| + cfg.update({'name': link['id']}) | |
| + for network in [net for net in networks | |
| + if net['link'] == link['id']]: | |
| + subnet = dict((k, v) for k, v in network.items() | |
| + if k in valid_keys['subnet']) | |
| + if 'dhcp' in network['type']: | |
| + t = 'dhcp6' if network['type'].startswith('ipv6') else 'dhcp4' | |
| + subnet.update({ | |
| + 'type': t, | |
| + }) | |
| else: | |
| - subnet['ipv4'] = True | |
| - subnets.append(subnet) | |
| - cfg.update({'subnets': subnets}) | |
| - if link['type'] in ['ethernet', 'vif', 'ovs', 'phy']: | |
| - cfg.update({ | |
| - 'type': 'physical', | |
| - 'mac_address': link['ethernet_mac_address']}) | |
| - elif link['type'] in ['bond']: | |
| - params = {} | |
| - for k, v in link.items(): | |
| - if k == 'bond_links': | |
| - continue | |
| - elif k.startswith('bond'): | |
| - params.update({k: v}) | |
| - cfg.update({ | |
| - 'bond_interfaces': copy.deepcopy(link['bond_links']), | |
| - 'params': params, | |
| - }) | |
| - elif link['type'] in ['vlan']: | |
| - cfg.update({ | |
| - 'name': "%s.%s" % (link['vlan_link'], | |
| - link['vlan_id']), | |
| - 'vlan_link': link['vlan_link'], | |
| - 'vlan_id': link['vlan_id'], | |
| - 'mac_address': link['vlan_mac_address'], | |
| - }) | |
| - elif link['type'] in ['bridge']: | |
| - cfg.update({ | |
| - 'type': 'bridge', | |
| - 'mac_address': link['ethernet_mac_address'], | |
| - 'mtu': link['mtu']}) | |
| - else: | |
| - raise ValueError( | |
| - 'Unknown network_data link type: %s' % link['type']) | |
| - | |
| - config.append(cfg) | |
| - | |
| - for service in services: | |
| - cfg = copy.deepcopy(service) | |
| - cfg.update({'type': 'nameserver'}) | |
| - config.append(cfg) | |
| - | |
| - return {'version': 1, 'config': config} | |
| + subnet.update({ | |
| + 'type': 'static', | |
| + 'address': network.get('ip_address'), | |
| + }) | |
| + if network['type'] == 'ipv6': | |
| + subnet['ipv6'] = True | |
| + else: | |
| + subnet['ipv4'] = True | |
| + subnets.append(subnet) | |
| + cfg.update({'subnets': subnets}) | |
| + if link['type'] in ['phy']: | |
| + cfg.update({ | |
| + 'type': 'physical', | |
| + 'mac_address': link['ethernet_mac_address'], | |
| + 'mtu': link['mtu']}) | |
| + elif link['type'] in ['bond']: | |
| + params = {} | |
| + for k, v in link.items(): | |
| + if k == 'bond_links': | |
| + continue | |
| + elif k.startswith('bond'): | |
| + params.update({k: v}) | |
| + cfg.update({ | |
| + 'bond_interfaces': copy.deepcopy(link['bond_links']), | |
| + 'params': params, | |
| + }) | |
| + elif link['type'] in ['vlan']: | |
| + cfg.update({ | |
| + 'name': "%s.%s" % (link['vlan_link'], | |
| + link['vlan_id']), | |
| + 'vlan_link': link['vlan_link'], | |
| + 'vlan_id': link['vlan_id'], | |
| + 'mac_address': link['vlan_mac_address'], | |
| + }) | |
| + else: | |
| + raise ValueError( | |
| + 'Unknown network_data link type: %s' % link['type']) | |
| + | |
| + config.append(cfg) | |
| + | |
| + for service in services: | |
| + cfg = copy.deepcopy(service) | |
| + cfg.update({'type': 'nameserver'}) | |
| + config.append(cfg) | |
| + | |
| + return {'version': 1, 'config': config} | |
| def convert_vendordata_json(data, recurse=True): |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment