May Cthulhu take mercy on my soul for this commit.

This is a bit of a refactor that may need to come with a documentation
update as well. It appears our previous authors made a few assumptions
for the sake of simplicity. Thankfully, they were nice enough to write
the rest of the system to be flexible enough for me to wedge this in.

I rewrote this so that it can handle an interface having v4-only,
v6-only, or v4-and-v6 addresses assigned. It's possible some options I
copied into the V6IF block are not valid inet6 options, but these can be
removed as needed

An IPv6 interface can have any number of IPv6 addresses attached to it,
this will also need to be included.
This commit is contained in:
Michael Lustfield 2016-12-04 20:47:27 -06:00
parent 300ca6047e
commit 525c746274
2 changed files with 147 additions and 51 deletions

View file

@ -1214,6 +1214,7 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
adapters[iface]['data'] = salt.utils.odict.OrderedDict()
iface_data = adapters[iface]['data']
iface_data['inet'] = salt.utils.odict.OrderedDict()
iface_data['inet6'] = salt.utils.odict.OrderedDict()
if enabled:
adapters[iface]['enabled'] = True
@ -1221,7 +1222,27 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
if opts.get('hotplug', False):
adapters[iface]['hotplug'] = True
iface_data['inet']['addrfam'] = 'inet'
def_addrfam = 'inet'
dual_stack = False
if 'enable_ipv6' in opts and opts['enable_ipv6']:
# If enable_ipv6=True, then *YES* inet6 will be there
iface_data['inet6']['addrfam'] = 'inet6'
iface_data['inet6']['netmask'] = '64' # defaults to 64
def_addrfam = 'inet6'
if 'iface_type' in opts and opts['iface_type'] == 'vlan':
iface_data['inet6']['vlan_raw_device'] = (
re.sub(r'\.\d*', '', iface))
if 'ipaddr' in opts or 'netmask' in opts or 'ipv6ipaddr' not in opts:
# At this point, we can be reasonably sure either ipv4-only or dual stack.
# If dual stack, then prefer the use of inet.
iface_data['inet']['addrfam'] = 'inet'
def_addrfam = 'inet'
if 'enable_ipv6' in opts and opts['enable_ipv6'] or 'ipv6addr' in opts:
dual_stack = True
if iface_type not in ['bridge']:
tmp_ethtool = _parse_ethtool_opts(opts, iface)
@ -1230,58 +1251,54 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
for item in tmp_ethtool:
ethtool[_ETHTOOL_CONFIG_OPTS[item]] = tmp_ethtool[item]
iface_data['inet']['ethtool'] = ethtool
iface_data[def_addrfam]['ethtool'] = ethtool
# return a list of sorted keys to ensure consistent order
iface_data['inet']['ethtool_keys'] = sorted(ethtool)
iface_data[def_addrfam]['ethtool_keys'] = sorted(ethtool)
if iface_type == 'bridge':
bridging = _parse_bridge_opts(opts, iface)
if bridging:
opts.pop('mode', None)
iface_data['inet']['bridging'] = bridging
iface_data['inet']['bridging_keys'] = sorted(bridging)
iface_data[def_addrfam]['bridging'] = bridging
iface_data[def_addrfam]['bridging_keys'] = sorted(bridging)
iface_data[def_addrfam]['addrfam'] = def_addrfam
elif iface_type == 'bond':
bonding = _parse_settings_bond(opts, iface)
if bonding:
opts.pop('mode', None)
iface_data['inet']['bonding'] = bonding
iface_data['inet']['bonding']['slaves'] = opts['slaves']
iface_data['inet']['bonding_keys'] = sorted(bonding)
iface_data[def_addrfam]['bonding'] = bonding
iface_data[def_addrfam]['bonding']['slaves'] = opts['slaves']
iface_data[def_addrfam]['bonding_keys'] = sorted(bonding)
iface_data[def_addrfam]['addrfam'] = def_addrfam
elif iface_type == 'slave':
adapters[iface]['master'] = opts['master']
opts['proto'] = 'manual'
iface_data['inet']['addrfam'] = 'inet'
iface_data['inet']['master'] = adapters[iface]['master']
iface_data[def_addrfam]['master'] = adapters[iface]['master']
iface_data[def_addrfam]['addrfam'] = def_addrfam
elif iface_type == 'vlan':
iface_data['inet']['vlan_raw_device'] = re.sub(r'\.\d*', '', iface)
iface_data[def_addrfam]['vlan_raw_device'] = re.sub(r'\.\d*', '', iface)
iface_data[def_addrfam]['addrfam'] = def_addrfam
elif iface_type == 'pppoe':
tmp_ethtool = _parse_ethtool_pppoe_opts(opts, iface)
if tmp_ethtool:
for item in tmp_ethtool:
adapters[iface]['data']['inet'][_DEB_CONFIG_PPPOE_OPTS[item]] = tmp_ethtool[item]
adapters[iface]['data'][def_addrfam][_DEB_CONFIG_PPPOE_OPTS[item]] = tmp_ethtool[item]
iface_data[def_addrfam]['addrfam'] = def_addrfam
if 'enable_ipv6' in opts and opts['enable_ipv6']: # TODO: check yes/no
# iface_data.append({})
iface_data['inet6'] = {}
iface_data['inet6']['addrfam'] = 'inet6'
iface_data['inet6']['netmask'] = '64' # defaults to 64
if 'iface_type' in opts and opts['iface_type'] == 'vlan':
iface_data['inet6']['vlan_raw_device'] = (
re.sub(r'\.\d*', '', iface))
for opt in opts:
# trim leading "ipv6" from option
if opt.startswith('ipv6'):
optname = opt[4:] # trim off the ipv6
addrfam = 'inet6'
v6only = True
else:
optname = opt
addrfam = 'inet'
v6only = False
_optname = SALT_ATTR_TO_DEBIAN_ATTR_MAP.get(optname, optname)
if _attrmaps_contain_attr(_optname):
@ -1291,25 +1308,72 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
if optname == 'proto' and valuestr == 'none':
valuestr = 'static'
(valid, value, errmsg) = _validate_interface_option(
_optname, valuestr, addrfam=addrfam)
# If option is v6-only, don't validate against inet and always set value
if v6only:
(valid, value, errmsg) = _validate_interface_option(
_optname, valuestr, addrfam='inet6')
if not valid:
_raise_error_iface(
iface,
'\'{0}\' \'{1}\''.format(opt, valuestr),
[errmsg]
)
if not valid:
_raise_error_iface(iface, '\'{0}\' \'{1}\''.format(opt, valuestr), [errmsg])
# replace dashes with underscores for jinja
_optname = _optname.replace('-', '_')
iface_data['inet6'][_optname] = value
# Else, if it's a dual stack, the option may belong in both; apply v4 opt as v6 default
elif dual_stack:
valid_once = False
errmsg = None
for addrfam in ['inet', 'inet6']:
(valid, value, errmsg) = _validate_interface_option(
_optname, valuestr, addrfam=addrfam)
if valid:
valid_once = True
# replace dashes with underscores for jinja
_optname = _optname.replace('-', '_')
# if a v6-only version of this option was set; don't override
# otherwise, if dual stack, use the v4 version as a default value for v6
# allows overriding with =None
if addrfam == 'inet' or _optname not in iface_data['inet6']:
iface_data[addrfam][_optname] = value
if not valid_once:
_raise_error_iface(
iface,
'\'{0}\' \'{1}\''.format(opt, valuestr),
[errmsg]
)
# Else, it goes in the default(only) addrfam
# Not assuming v4 allows a v6 block to be created without lots of "ipv6" prefixes
else:
(valid, value, errmsg) = _validate_interface_option(
_optname, valuestr, addrfam=def_addrfam)
if not valid:
_raise_error_iface(
iface,
'\'{0}\' \'{1}\''.format(opt, valuestr),
[errmsg]
)
# replace dashes with underscores for jinja
_optname = _optname.replace('-', '_')
iface_data[def_addrfam][_optname] = value
# replace dashes with underscores for jinja
_optname = _optname.replace('-', '_')
iface_data[addrfam][_optname] = value
for opt in ['up_cmds', 'pre_up_cmds', 'post_up_cmds',
'down_cmds', 'pre_down_cmds', 'post_down_cmds']:
if opt in opts:
iface_data['inet'][opt] = opts[opt]
for addrfam in ['inet', 'inet6']:
if 'addrfam' in iface_data[addrfam] and iface_data[addrfam]['addrfam'] == addrfam:
pass
else:
iface_data.pop(addrfam)
return adapters

View file

@ -1,9 +1,8 @@
{% if data.enabled %}auto {{name}}{# Enabled #}
{%endif%}{% if data.hotplug %}allow-hotplug {{name}}{# Hotplug #}
{%endif%}{%- if data.data['inet'] and data.data['inet'].addrfam == 'inet' -%}{# IPv4 #}
{%- set interface = data.data['inet'] -%}
{% if interface.proto and interface.addrfam == 'inet' %}iface {{name}} {{interface.addrfam}} {{interface.proto}}
{%endif%}{% if interface.hwaddress %} hwaddress {{interface.hwaddress}}
{%endif%}{# START IPV4 #}{%- if data.data['inet'] and data.data['inet'].addrfam == 'inet' -%}{% set interface = data.data['inet'] -%}
{# START V4IF #}{% if interface.proto and interface.addrfam %}iface {{name}} {{interface.addrfam}} {{interface.proto}}
{% if interface.hwaddress %} hwaddress {{interface.hwaddress}}
{%endif%}{% if interface.vlan_raw_device %} vlan-raw-device {{interface.vlan_raw_device}}
{%endif%}{% if interface.address %} address {{interface.address}}
{%endif%}{% if interface.netmask %} netmask {{interface.netmask}}
@ -13,7 +12,7 @@
{%endif%}{% if interface.pointopoint %} pointopoint {{interface.pointopoint}}
{%endif%}{% if interface.scope %} scope {{interface.scope}}
{%endif%}{% if interface.hostname %} hostname {{interface.hostname}}
{%endif%}{% if interface.metric %} metric {{interface.metric}}
{%endif%}{% if interface.media %} media {{interface.media}}
{%endif%}{% if interface.leasehours %} leasehours {{interface.leasehours}}
{%endif%}{% if interface.leasetime %} leasetime {{interface.leasetime}}
{%endif%}{% if interface.vendor %} vendor {{interface.vendor}}
@ -59,26 +58,59 @@
{%endif%}{% if interface.pre_down_cmds %}{% for cmd in interface.pre_down_cmds %} pre-down {{ cmd }}
{%endfor-%}
{%endif%}{% if interface.post_down_cmds %}{% for cmd in interface.post_down_cmds %} post-down {{ cmd }}
{%endfor-%}{%endif%}
{%- endif%}
{%- if data.data['inet6'] and data.data['inet6'].addrfam == 'inet6' -%}{# IPv6 #}
{%- set interface = data.data['inet6'] -%}
{% if interface.proto and interface.addrfam == 'inet6' %}iface {{name}} {{interface.addrfam}} {{interface.proto}}
{%endif%}{% if interface.hwaddress %} hwaddress {{interface.hwaddress}}
{%endfor-%}{%endif%}{%endif%}{# END V4IF #}
{%- endif%}{# END IPV4 -#}
{#- START IPV6 #}{%- if data.data['inet6'] and data.data['inet6'].addrfam == 'inet6' -%}{%- set interface = data.data['inet6'] -%}
{#- START V6IF -#}{% if interface.proto and interface.addrfam %}iface {{name}} {{interface.addrfam}} {{interface.proto}}
{% if interface.hwaddress %} hwaddress {{interface.hwaddress}}
{%endif%}{# START V6ONLOPTS #}{% if interface.accept_ra %} accept_ra {{interface.accept_ra}}
{%endif%}{% if interface.autoconf %} autoconf {{interface.autoconf}}
{%endif%}{% if interface.privext %} privext {{interface.privext}}
{%endif%}{% if interface.dhcp %} dhcp {{interface.dhcp}}{# END V6ONLOPTS #}
{%endif%}{% if interface.vlan_raw_device %} vlan-raw-device {{interface.vlan_raw_device}}
{%endif%}{% if interface.address %} address {{interface.address}}
{%endif%}{% if interface.netmask %} netmask {{interface.netmask}}
{%endif%}{% if interface.broadcast %} broadcast {{interface.broadcast}}
{%endif%}{% if interface.metric %} metric {{interface.metric}}
{%endif%}{% if interface.gateway %} gateway {{interface.gateway}}
{%endif%}{% if interface.pointopoint %} pointopoint {{interface.pointopoint}}
{%endif%}{% if interface.scope %} scope {{interface.scope}}
{%endif%}{% if interface.hostname %} hostname {{interface.hostname}}
{%endif%}{% if interface.media %} media {{interface.media}}
{%endif%}{% if interface.leasehours %} leasehours {{interface.leasehours}}
{%endif%}{% if interface.leasetime %} leasetime {{interface.leasetime}}
{%endif%}{% if interface.vendor %} vendor {{interface.vendor}}
{%endif%}{% if interface.client %} client {{interface.client}}
{%endif%}{% if interface.bootfile %} bootfile {{interface.bootfile}}
{%endif%}{% if interface.server %} server {{interface.server}}
{%endif%}{% if interface.hwaddr %} hwaddress {{interface.hwaddr}}
{%endif%}{% if interface.mode %} mode {{interface.mode}}
{%endif%}{% if interface.endpoint %} endpoint {{interface.endpoint}}
{%endif%}{% if interface.dstaddr %} dstaddr {{interface.dstaddr}}
{%endif%}{% if interface.local %} local {{interface.local}}
{%endif%}{% if interface.ttl %} ttl {{interface.ttl}}
{%endif%}{% if interface.mtu %} mtu {{interface.mtu}}
{%endif%}{% if interface.accept_ra %} accept_ra {{interface.accept_ra}}
{%endif%}{% if interface.autoconf %} autoconf {{interface.autoconf}}
{%endif%}{% if interface.privext %} privext {{interface.privext}}
{%endif%}{% if interface.dhcp %} dhcp {{interface.dhcp}}
{%endif%}{% if interface.scope %} scope {{interface.scope}}
{%endif%}{% if interface.provider %} provider {{interface.provider}}
{%endif%}{% if interface.unit %} unit {{interface.unit}}
{%endif%}{% if interface.options %} options {{interface.options}}
{%endif%}{% if interface.master %} bond-master {{interface.master}}
{%endif%}{% if interface.dns_nameservers %} dns-nameservers {%for item in interface.dns_nameservers %}{{item}} {%endfor%}
{%endif%}{% if interface.dns_search %} dns-search {% for item in interface.dns_search %}{{item}} {%endfor%}
{%endif%}{% if interface.ethtool %}{%for item in interface.ethtool_keys %} {{item}} {{interface.ethtool[item]}}
{%endfor%}{%endif%}{% if interface.bonding %}{%for item in interface.bonding_keys %} bond-{{item}} {{interface.bonding[item]}}
{%endfor%}{%endif%}{% if interface.bridging %}{%for item in interface.bridging_keys %} bridge_{{item}} {{interface.bridging[item]}}
{%endfor%}{%endif%}{% if interface.wireless_essid %} wireless-essid {{interface.wireless_essid}}
{%endif%}{% if interface.wireless_mode %} wireless-mode {{interface.wireless_mode}}
{%endif%}{% if interface.wpa_ap_scan %} wpa-ap-scan {{interface.wpa_ap_scan}}
{%endif%}{% if interface.wpa_conf %} wpa-conf {{interface.wpa_conf}}
{%endif%}{% if interface.wpa_driver %} wpa-driver {{interface.wpa_driver}}
{%endif%}{% if interface.wpa_group %} wpa-group {{interface.wpa_group}}
{%endif%}{% if interface.wpa_key_mgmt %} wpa-key-mgmt {{interface.wpa_key_mgmt}}
{%endif%}{% if interface.wpa_pairwise %} wpa-pairwise {{interface.wpa_pairwise}}
{%endif%}{% if interface.wpa_proto %} wpa-proto {{interface.wpa_proto}}
{%endif%}{% if interface.wpa_psk %} wpa-psk {{interface.wpa_psk}}
{%endif%}{% if interface.wpa_roam %} wpa-roam {{interface.wpa_roam}}
{%endif%}{% if interface.wpa_ssid %} wpa-ssid {{interface.wpa_ssid}}
{%endif%}{% if interface.up_cmds %}{% for cmd in interface.up_cmds %} up {{ cmd }}
{%endfor-%}
{%endif%}{% if interface.down_cmds %}{% for cmd in interface.down_cmds %} down {{ cmd }}
@ -90,4 +122,4 @@
{%endif%}{% if interface.pre_down_cmds %}{% for cmd in interface.pre_down_cmds %} pre-down {{ cmd }}
{%endfor-%}
{%endif%}{% if interface.post_down_cmds %}{% for cmd in interface.post_down_cmds %} post-down {{ cmd }}
{%endfor-%}{%endif%}{%endif%}
{%endfor-%}{%endif%}{%endif%}{# END V6IF #}{%endif%}{# END IPV6#}