Skip to content

Instantly share code, notes, and snippets.

@harlowja
Created May 25, 2016 22:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harlowja/12e0a56ff0ee0182cc943f966bef8ec0 to your computer and use it in GitHub Desktop.
Save harlowja/12e0a56ff0ee0182cc943f966bef8ec0 to your computer and use it in GitHub Desktop.
=== 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