mirror of
https://github.com/xcat2/confluent.git
synced 2026-07-21 00:27:28 +00:00
Add net.extra_settings for passthrough network settings
Allow arbitrary per-connection network settings, such as static routes or a firewalld zone, to be specified as semicolon-delimited key=value pairs on a net.*.extra_settings attribute. The keys are passed through to the network backend of the deployed OS in its native syntax: nmcli properties on NetworkManager systems, netplan YAML paths on netplan systems, and ifcfg variables on wicked systems.
This commit is contained in:
@@ -130,6 +130,21 @@ to a blank value will allow masking a group defined attribute with an empty valu
|
||||
`node12: net.compute.ipv4_address: 172.17.0.12/16`
|
||||
`node12: net.compute.team_mode: lacp`
|
||||
|
||||
* Passing additional settings to the network backend of the deployed OS with `net.extra_settings`
|
||||
(semicolon-delimited key=value pairs, keys in the native syntax of the respective backend).
|
||||
On a NetworkManager based OS (e.g. Enterprise Linux), keys are nmcli properties:
|
||||
`# nodeattrib node12 net.mgmt.extra_settings='connection.zone=internal;ipv4.routes=10.0.0.0/8 192.168.1.254, 172.16.0.0/12 192.168.1.254;ipv4.route-metric=200'`
|
||||
`node12: net.mgmt.extra_settings: connection.zone=internal;ipv4.routes=10.0.0.0/8 192.168.1.254, 172.16.0.0/12 192.168.1.254;ipv4.route-metric=200`
|
||||
|
||||
* On a netplan based OS (e.g. Ubuntu), keys are netplan YAML paths (nested keys dotted, values in YAML flow syntax).
|
||||
Since Confluent uses braces for attribute expressions, literal braces must be escaped as `{{` and `}}` when setting the attribute:
|
||||
`# nodeattrib node13 net.mgmt.extra_settings='routes=[{{to: 10.0.0.0/8, via: 192.168.1.254}}];nameservers.search=[lab.example.com]'`
|
||||
`node13: net.mgmt.extra_settings: routes=[{to: 10.0.0.0/8, via: 192.168.1.254}];nameservers.search=[lab.example.com]`
|
||||
|
||||
* On a wicked based OS (e.g. SUSE), keys are ifcfg variables (routes are not supported through this mechanism on wicked):
|
||||
`# nodeattrib node14 net.mgmt.extra_settings='ZONE=internal;ETHTOOL_OPTIONS=-K iface tso off'`
|
||||
`node14: net.mgmt.extra_settings: ZONE=internal;ETHTOOL_OPTIONS=-K iface tso off`
|
||||
|
||||
* Clear attribute on nodes of a simple noderange, if you want to retain the variable set the attribute to "":
|
||||
`# nodeattrib n1-n2 -c console.method`
|
||||
`# nodeattrib n1-n2 console.method`
|
||||
|
||||
@@ -114,6 +114,14 @@ def get_interface_name(iname, settings):
|
||||
return iname
|
||||
return None
|
||||
|
||||
def parse_extra_settings(stgs):
|
||||
extras = {}
|
||||
for kv in stgs.get('extra_settings', '').split(';'):
|
||||
k, _, v = kv.partition('=')
|
||||
if k.strip():
|
||||
extras[k.strip()] = v.strip()
|
||||
return extras
|
||||
|
||||
class NetplanManager(object):
|
||||
def __init__(self, deploycfg):
|
||||
self.cfgbydev = {}
|
||||
@@ -229,6 +237,24 @@ class NetplanManager(object):
|
||||
if dnsdomain not in currdnsdomain:
|
||||
needcfgwrite = True
|
||||
currdnsdomain.append(dnsdomain)
|
||||
extras = parse_extra_settings(stgs)
|
||||
if extras:
|
||||
currcfg = self.cfgbybond if devname in self.cfgbybond else self.cfgbydev
|
||||
devdict = currcfg.setdefault(devname, {})
|
||||
for key in extras:
|
||||
try:
|
||||
val = yaml.safe_load(extras[key])
|
||||
except yaml.YAMLError:
|
||||
val = extras[key]
|
||||
keyptr = devdict
|
||||
keypath = key.split('.')
|
||||
for k in keypath[:-1]:
|
||||
if not isinstance(keyptr.get(k, None), dict):
|
||||
keyptr[k] = {}
|
||||
keyptr = keyptr[k]
|
||||
if keyptr.get(keypath[-1], None) != val:
|
||||
needcfgwrite = True
|
||||
keyptr[keypath[-1]] = val
|
||||
prune_from_cloudinit = []
|
||||
if needcfgwrite:
|
||||
needcfgapply = True
|
||||
@@ -336,6 +362,9 @@ class WickedManager(object):
|
||||
if stgs.get('ipv6_address', None):
|
||||
ipcfg += 'IPADDR_V6=' + stgs['ipv6_address'] + '\n'
|
||||
v6gw = stgs.get('ipv6_gateway', None)
|
||||
extras = parse_extra_settings(stgs)
|
||||
for key in extras:
|
||||
ipcfg += '{0}={1}\n'.format(key, shlex.quote(extras[key]))
|
||||
cname = None
|
||||
if len(cfg['interfaces']) > 1: # creating new team
|
||||
if not stgs.get('team_mode', None):
|
||||
@@ -475,6 +504,7 @@ class NetworkManager(object):
|
||||
cmdargs['ipv4.dns'] = ','.join(dns4)
|
||||
if dns6:
|
||||
cmdargs['ipv6.dns'] = ','.join(dns6)
|
||||
cmdargs.update(parse_extra_settings(stgs))
|
||||
if len(cfg['interfaces']) > 1: # team time.. should be..
|
||||
if not cfg['settings'].get('team_mode', None):
|
||||
sys.stderr.write("Warning, multiple interfaces ({0}) without a team_mode, skipping setup\n".format(','.join(cfg['interfaces'])))
|
||||
|
||||
@@ -111,6 +111,14 @@ def get_interface_name(iname, settings):
|
||||
return iname
|
||||
return None
|
||||
|
||||
def parse_extra_settings(stgs):
|
||||
extras = {}
|
||||
for kv in stgs.get('extra_settings', '').split(';'):
|
||||
k, _, v = kv.partition('=')
|
||||
if k.strip():
|
||||
extras[k.strip()] = v.strip()
|
||||
return extras
|
||||
|
||||
class NetplanManager(object):
|
||||
def __init__(self, deploycfg):
|
||||
self.cfgbydev = {}
|
||||
@@ -192,6 +200,23 @@ class NetplanManager(object):
|
||||
if dnsdomain not in currdnsdomain:
|
||||
needcfgwrite = True
|
||||
currdnsdomain.append(dnsdomain)
|
||||
extras = parse_extra_settings(stgs)
|
||||
if extras:
|
||||
devdict = self.cfgbydev.setdefault(devname, {})
|
||||
for key in extras:
|
||||
try:
|
||||
val = yaml.safe_load(extras[key])
|
||||
except yaml.YAMLError:
|
||||
val = extras[key]
|
||||
keyptr = devdict
|
||||
keypath = key.split('.')
|
||||
for k in keypath[:-1]:
|
||||
if not isinstance(keyptr.get(k, None), dict):
|
||||
keyptr[k] = {}
|
||||
keyptr = keyptr[k]
|
||||
if keyptr.get(keypath[-1], None) != val:
|
||||
needcfgwrite = True
|
||||
keyptr[keypath[-1]] = val
|
||||
if needcfgwrite:
|
||||
needcfgapply = True
|
||||
newcfg = {'network': {'version': 2, 'ethernets': {devname: self.cfgbydev[devname]}}}
|
||||
@@ -261,6 +286,9 @@ class WickedManager(object):
|
||||
if stgs.get('ipv6_address', None):
|
||||
ipcfg += 'IPADDR_V6=' + stgs['ipv6_address'] + '\n'
|
||||
v6gw = stgs.get('ipv6_gateway', None)
|
||||
extras = parse_extra_settings(stgs)
|
||||
for key in extras:
|
||||
ipcfg += '{0}={1}\n'.format(key, shlex.quote(extras[key]))
|
||||
cname = None
|
||||
if len(cfg['interfaces']) > 1: # creating new team
|
||||
if not stgs.get('team_mode', None):
|
||||
@@ -400,6 +428,7 @@ class NetworkManager(object):
|
||||
cmdargs['ipv4.dns'] = ','.join(dns4)
|
||||
if dns6:
|
||||
cmdargs['ipv6.dns'] = ','.join(dns6)
|
||||
cmdargs.update(parse_extra_settings(stgs))
|
||||
if len(cfg['interfaces']) > 1: # team time.. should be..
|
||||
if not cfg['settings'].get('team_mode', None):
|
||||
sys.stderr.write("Warning, multiple interfaces ({0}) without a team_mode, skipping setup\n".format(','.join(cfg['interfaces'])))
|
||||
|
||||
@@ -589,6 +589,16 @@ node = {
|
||||
'To support this scenario, the switch should be set up to allow independent operation of member ports (e.g. lacp bypass mode or fallback mode).',
|
||||
'validvalues': ('lacp', 'loadbalance', 'roundrobin', 'activebackup', 'none')
|
||||
},
|
||||
'net.extra_settings': {
|
||||
'description': 'Additional network settings to apply to the connection, as '
|
||||
'semicolon-delimited key=value pairs (e.g. '
|
||||
'"connection.zone=internal;ipv4.routes=10.0.0.0/8 192.168.1.254"). '
|
||||
'The keys are passed through to the network configuration backend of '
|
||||
'the deployed OS and use its native syntax: nmcli property names on '
|
||||
'NetworkManager based systems, netplan YAML keys (values in YAML flow '
|
||||
'syntax, nested keys dotted) on netplan based systems, or ifcfg '
|
||||
'variables on wicked based systems.',
|
||||
},
|
||||
'power.pdu': {
|
||||
'description': 'Specifies the managed PDU associated with a power input on the node'
|
||||
},
|
||||
|
||||
@@ -246,6 +246,9 @@ class NetManager(object):
|
||||
teammod = attribs.get('team_mode', None)
|
||||
if teammod:
|
||||
myattribs['team_mode'] = teammod
|
||||
extrastgs = attribs.get('extra_settings', None)
|
||||
if extrastgs:
|
||||
myattribs['extra_settings'] = extrastgs
|
||||
method = attribs.get('ipv4_method', None)
|
||||
if method != 'dhcp':
|
||||
ipv4addr = attribs.get('ipv4_address', None)
|
||||
|
||||
Reference in New Issue
Block a user