Skip to content

Commit

Permalink
Removed distro specific network code from Photon (#929)
Browse files Browse the repository at this point in the history
Minor fixes in networkd renderer & fixed corresponding tests

Removed datasource_list for Photon from cloud.cfg.tmpl & added a comment
in cloud.cfg.tmpl about not to use multiline array for datasource_list.

Signed-off-by: Shreenidhi Shedi <sshedi@vmware.com>
  • Loading branch information
sshedi committed Jun 28, 2021
1 parent 35aa9db commit b5aecbe
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 246 deletions.
217 changes: 0 additions & 217 deletions cloudinit/distros/photon.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@
from cloudinit import distros
from cloudinit import helpers
from cloudinit import log as logging
from cloudinit.distros import net_util
from cloudinit.settings import PER_INSTANCE
from cloudinit.distros import rhel_util as rhutil
from cloudinit.net.network_state import mask_to_net_prefix
from cloudinit.distros.parsers.hostname import HostnameConf

LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -79,9 +77,6 @@ def install_packages(self, pkglist):
self.package_command('install', pkgs=pkglist)

def _write_network_config(self, netconfig):
if isinstance(netconfig, str):
self._write_network_(netconfig)
return
return self._supported_write_network_config(netconfig)

def _bring_up_interfaces(self, device_names):
Expand Down Expand Up @@ -141,215 +136,3 @@ def package_command(self, command, args=None, pkgs=None):
def update_package_sources(self):
self._runner.run('update-sources', self.package_command,
['makecache'], freq=PER_INSTANCE)

def _generate_resolv_conf(self):
resolv_conf_fn = self.resolve_conf_fn
resolv_templ_fn = 'systemd.resolved.conf'

return resolv_conf_fn, resolv_templ_fn

def _write_network_(self, settings):
entries = net_util.translate_network(settings)
LOG.debug('Translated ubuntu style network settings %s into %s',
settings, entries)
route_entries = []
route_entries = translate_routes(settings)
dev_names = entries.keys()
nameservers = []
searchdomains = []
# Format for systemd
for (dev, info) in entries.items():
if 'dns-nameservers' in info:
nameservers.extend(info['dns-nameservers'])
if 'dns-search' in info:
searchdomains.extend(info['dns-search'])
if dev == 'lo':
continue

net_fn = self.network_conf_dir + '10-cloud-init-' + dev
net_fn += '.network'
dhcp_enabled = 'no'
if info.get('bootproto') == 'dhcp':
if (settings.find('inet dhcp') >= 0 and
settings.find('inet6 dhcp') >= 0):
dhcp_enabled = 'yes'
else:
if info.get('inet6') is True:
dhcp_enabled = 'ipv6'
else:
dhcp_enabled = 'ipv4'

net_cfg = {
'Name': dev,
'DHCP': dhcp_enabled,
}

if info.get('hwaddress'):
net_cfg['MACAddress'] = info.get('hwaddress')
if info.get('address'):
net_cfg['Address'] = '%s' % (info.get('address'))
if info.get('netmask'):
net_cfg['Address'] += '/%s' % (
mask_to_net_prefix(info.get('netmask')))
if info.get('gateway'):
net_cfg['Gateway'] = info.get('gateway')
if info.get('dns-nameservers'):
net_cfg['DNS'] = str(
tuple(info.get('dns-nameservers'))).replace(',', '')
if info.get('dns-search'):
net_cfg['Domains'] = str(
tuple(info.get('dns-search'))).replace(',', '')
route_entry = []
if dev in route_entries:
route_entry = route_entries[dev]
route_index = 0
found = True
while found:
route_name = 'routes.' + str(route_index)
if route_name in route_entries[dev]:
val = str(tuple(route_entries[dev][route_name]))
val = val.replace(',', '')
if val:
net_cfg[route_name] = val
else:
found = False
route_index += 1

if info.get('auto'):
self._write_interface_file(net_fn, net_cfg, route_entry)

resolve_data = []
new_resolve_data = []
with open(self.resolve_conf_fn, 'r') as rf:
resolve_data = rf.readlines()
LOG.debug('Old Resolve Data\n')
LOG.debug('%s', resolve_data)
for item in resolve_data:
if ((nameservers and ('DNS=' in item)) or
(searchdomains and ('Domains=' in item))):
continue
else:
new_resolve_data.append(item)

new_resolve_data = new_resolve_data + \
convert_resolv_conf(nameservers, searchdomains)
LOG.debug('New resolve data\n')
LOG.debug('%s', new_resolve_data)
if nameservers or searchdomains:
util.write_file(self.resolve_conf_fn, ''.join(new_resolve_data))

return dev_names

def _write_interface_file(self, net_fn, net_cfg, route_entry):
if not net_cfg['Name']:
return
content = '[Match]\n'
content += 'Name=%s\n' % (net_cfg['Name'])
if 'MACAddress' in net_cfg:
content += 'MACAddress=%s\n' % (net_cfg['MACAddress'])
content += '[Network]\n'

if 'DHCP' in net_cfg and net_cfg['DHCP'] in {'yes', 'ipv4', 'ipv6'}:
content += 'DHCP=%s\n' % (net_cfg['DHCP'])
else:
if 'Address' in net_cfg:
content += 'Address=%s\n' % (net_cfg['Address'])
if 'Gateway' in net_cfg:
content += 'Gateway=%s\n' % (net_cfg['Gateway'])
if 'DHCP' in net_cfg and net_cfg['DHCP'] == 'no':
content += 'DHCP=%s\n' % (net_cfg['DHCP'])

route_index = 0
found = True
if route_entry:
while found:
route_name = 'routes.' + str(route_index)
if route_name in route_entry:
content += '[Route]\n'
if len(route_entry[route_name]) != 2:
continue
content += 'Gateway=%s\n' % (
route_entry[route_name][0])
content += 'Destination=%s\n' % (
route_entry[route_name][1])
else:
found = False
route_index += 1

util.write_file(net_fn, content)


def convert_resolv_conf(nameservers, searchdomains):
''' Returns a string formatted for resolv.conf '''
result = []
if nameservers:
nslist = 'DNS='
for ns in nameservers:
nslist = nslist + '%s ' % ns
nslist = nslist + '\n'
result.append(str(nslist))
if searchdomains:
sdlist = 'Domains='
for sd in searchdomains:
sdlist = sdlist + '%s ' % sd
sdlist = sdlist + '\n'
result.append(str(sdlist))
return result


def translate_routes(settings):
entries = []
for line in settings.splitlines():
line = line.strip()
if not line or line.startswith('#'):
continue
split_up = line.split(None, 1)
if len(split_up) <= 1:
continue
entries.append(split_up)
consume = {}
ifaces = []
for (cmd, args) in entries:
if cmd == 'iface':
if consume:
ifaces.append(consume)
consume = {}
consume[cmd] = args
else:
consume[cmd] = args

absorb = False
for (cmd, args) in consume.items():
if cmd == 'iface':
absorb = True
if absorb:
ifaces.append(consume)
out_ifaces = {}
for info in ifaces:
if 'iface' not in info:
continue
iface_details = info['iface'].split(None)
dev_name = None
if len(iface_details) >= 1:
dev = iface_details[0].strip().lower()
if dev:
dev_name = dev
if not dev_name:
continue
route_info = {}
route_index = 0
found = True
while found:
route_name = 'routes.' + str(route_index)
if route_name in info:
val = info[route_name].split()
if val:
route_info[route_name] = val
else:
found = False
route_index += 1
if dev_name in out_ifaces:
out_ifaces[dev_name].update(route_info)
else:
out_ifaces[dev_name] = route_info
return out_ifaces
51 changes: 32 additions & 19 deletions cloudinit/net/networkd.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ def update_section(self, sec, key, val):
for k in self.conf_dict.keys():
if k == sec:
self.conf_dict[k].append(key+'='+str(val))
# remove duplicates from list
self.conf_dict[k] = list(dict.fromkeys(self.conf_dict[k]))
self.conf_dict[k].sort()

def get_final_conf(self):
Expand Down Expand Up @@ -103,19 +105,27 @@ def generate_link_section(self, iface, cfg):

def parse_routes(self, conf, cfg):
sec = 'Route'
route_cfg_map = {
'gateway': 'Gateway',
'network': 'Destination',
'metric': 'Metric',
}

# prefix is derived using netmask by network_state
prefix = ''
if 'prefix' in conf:
prefix = '/' + str(conf['prefix'])

for k, v in conf.items():
if k == 'gateway':
cfg.update_section(sec, 'Gateway', v)
elif k == 'network':
tmp = v
if 'prefix' in conf:
tmp += '/' + str(conf['prefix'])
cfg.update_section(sec, 'Destination', tmp)
elif k == 'metric':
cfg.update_section(sec, 'Metric', v)
if k not in route_cfg_map:
continue
if k == 'network':
v += prefix
cfg.update_section(sec, route_cfg_map[k], v)

def parse_subnets(self, iface, cfg):
dhcp = 'no'
sec = 'Network'
for e in iface.get('subnets', []):
t = e['type']
if t == 'dhcp4' or t == 'dhcp':
Expand All @@ -131,21 +141,24 @@ def parse_subnets(self, iface, cfg):
if 'routes' in e and e['routes']:
for i in e['routes']:
self.parse_routes(i, cfg)
elif 'address' in e:
if 'address' in e:
subnet_cfg_map = {
'address': 'Address',
'gateway': 'Gateway',
'dns_nameservers': 'DNS',
'dns_search': 'Domains',
}
for k, v in e.items():
if k == 'address':
tmp = v
if 'prefix' in e:
tmp += '/' + str(e['prefix'])
cfg.update_section('Address', 'Address', tmp)
v += '/' + str(e['prefix'])
cfg.update_section('Address', subnet_cfg_map[k], v)
elif k == 'gateway':
cfg.update_section('Route', 'Gateway', v)
elif k == 'dns_nameservers':
cfg.update_section('Network', 'DNS', ' '.join(v))
elif k == 'dns_search':
cfg.update_section('Network', 'Domains', ' '.join(v))
cfg.update_section('Route', subnet_cfg_map[k], v)
elif k == 'dns_nameservers' or k == 'dns_search':
cfg.update_section(sec, subnet_cfg_map[k], ' '.join(v))

cfg.update_section('Network', 'DHCP', dhcp)
cfg.update_section(sec, 'DHCP', dhcp)

# This is to accommodate extra keys present in VMware config
def dhcp_domain(self, d, cfg):
Expand Down
12 changes: 2 additions & 10 deletions config/cloud.cfg.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,12 @@ ssh_pwauth: 0
# This will cause the set+update hostname module to not operate (if true)
preserve_hostname: false

# If you use datasource_list array, keep array items in a single line.
# If you use multi line array, ds-identify script won't read array items.
{% if variant.endswith("bsd") %}
# This should not be required, but leave it in place until the real cause of
# not finding -any- datasources is resolved.
datasource_list: ['NoCloud', 'ConfigDrive', 'Azure', 'OpenStack', 'Ec2']
{% elif variant in ["photon"] %}
# Datasources to check for cloud-config
datasource_list: [
NoCloud,
ConfigDrive,
OVF,
OpenStack,
VMwareGuestInfo,
None
]
{% endif %}
# Example datasource config
# datasource:
Expand Down

0 comments on commit b5aecbe

Please sign in to comment.