diff --git a/confluent_osdeploy/common/profile/scripts/confignet b/confluent_osdeploy/common/profile/scripts/confignet index e7ecc3fa..f44e6f4a 100644 --- a/confluent_osdeploy/common/profile/scripts/confignet +++ b/confluent_osdeploy/common/profile/scripts/confignet @@ -8,6 +8,10 @@ import sys import time import shlex import subprocess +try: + import yaml +except ImportError: + pass try: from importlib.machinery import SourceFileLoader def load_source(mod, path): @@ -107,6 +111,80 @@ def get_interface_name(iname, settings): return iname return None +class NetplanManager(object): + def __init__(self): + self.cfgbydev = {} + self.read_connections() + + def read_connections(self): + for plan in glob.glob('/etc/netplan/*.y*ml'): + with open(plan) as planfile: + planinfo = yaml.safe_load(planfile) + if not planinfo: + continue + nicinfo = planinfo.get('network', {}).get('ethernets', {}) + for devname in nicinfo: + if devname == 'lo': + continue + if 'gateway4' in nicinfo[devname]: + # normalize deprecated syntax on read in + gw4 = nicinfo[devname]['gateway4'] + del nicinfo[devname]['gateway4'] + routeinfo = nicinfo[devname].get('routes', []) + for ri in routeinfo: + if ri.get('via', None) == gw4 and ri.get('to', None) in ('default', '0.0.0.0/0', '0/0'): + break + else: + routeinfo.append({ + 'to': 'default', + 'via': gw4 + }) + nicinfo[devname]['routes'] = routeinfo + self.cfgbydev[devname] = nicinfo[devname] + + def apply_configuration(self, cfg): + devnames = cfg['interfaces'] + if len(devnames) != 1: + raise Exception('Multi-nic team/bonds not yet supported') + stgs = cfg['settings'] + needcfgapply = False + for devname in devnames: + needcfgwrite = False + if stgs['ipv4_method'] == 'static': + curraddr = stgs['ipv4_address'] + currips = self.getcfgarrpath([devname, 'addresses']) + if curraddr not in currips: + needcfgwrite = True + currips.append(curraddr) + gwaddr = stgs.get('ipv4_gateway', None) + if gwaddr: + cfgroutes = self.getcfgarrpath([devname, 'routes']) + for rinfo in cfgroutes: + if rinfo.get('via', None) == gwaddr: + break + else: + needcfgwrite = True + cfgroutes.append({'via': gwaddr, 'to': 'default'}) + if needcfgwrite: + needcfgaply = True + newcfg = {'network': {'version': 2, 'ethernets': {devname: self.cfgbydev[devname]}}} + with open('/etc/netplan/{0}-confluentcfg.yaml'.format(devname), 'w') as planout: + planout.write(yaml.dump(newcfg)) + if needcfgapply: + subprocess.call(['netplan', 'apply']) + + def getcfgarrpath(self, devpath): + currptr = self.cfgbydev + for k in devpath[:-1]: + if k not in currptr: + currptr[k] = {} + currptr = currptr[k] + if devpath[-1] not in currptr: + currptr[devpath[-1]] = [] + return currptr[devpath[-1]] + + + class WickedManager(object): def __init__(self): self.teamidx = 0 @@ -360,6 +438,8 @@ if __name__ == '__main__': if not netname_to_interfaces['default']['interfaces']: del netname_to_interfaces['default'] rm_tmp_llas(tmpllas) + if os.path.exists('/usr/sbin/netplan'): + nm = NetplanManager() if os.path.exists('/usr/bin/nmcli'): nm = NetworkManager(devtypes) elif os.path.exists('/usr/sbin/wicked'):