terminal length default 0
no ip http server
line console
line telnet
line ssh

port-channel load-balance src-dst-ip

ip ssh server

vlan {{ vlans | map(attribute='vid') | compact_numlist }}

{# bond members #}
{% for iface in interfaces | selectattr('lag') %}
interface {{ iface.name }}
{% if iface.enabled %} no{% endif %} shutdown
 channel-group {{ iface.lag.name | select('in', '0123456789') | join('') }} mode active

{% endfor %}

{# access interfaces #}
{%- set mgmt = namespace(ip=false, gw=false) %}
{%- for iface in interfaces | rejectattr('lag') %}
interface {{ iface.name }}
{# common setup for user-facing interfaces #}
{% if iface.type.value != 'lag' and not iface.mgmt_only %}
 switchport port-security
 switchport port-security maximum 250
 switchport port-security violation shutdown
 switchport port-security aging time 5
 switchport port-security aging type inactivity
{% if iface.enabled %} no shutdown{% else %} shutdown{% endif %}
{% endif %}

{# set VLAN for untagged ports #}
{%+ if iface.mode and iface.mode.value == 'access' %}
 switchport mode access
{% if iface.untagged_vlan and iface.untagged_vlan.vid != 1 %}
 switchport access vlan {{ iface.untagged_vlan.vid }}
{% else %}
 no switchport access vlan
{% endif %}
{% if voice_vlan is defined and not iface.mgmt_only %}
 voice vlan enable
{% else %}
 no voice vlan enable
{% endif %}

{# set tagged and native VLANs for tagged ports #}
{# if native (untagged) VLAN is set, add it to the list of tagged VLANs #}
{# without this, the switch won’t forward traffic #}
{%+ elif iface.mode and iface.mode.value == 'tagged' %}
 switchport mode trunk
{% if iface.untagged_vlan %}
{% set iface_vlans = (iface.tagged_vlans or vlans) + [iface.untagged_vlan] %}
 switchport trunk native vlan {{ iface.untagged_vlan.vid }}
{% else %}
{% set iface_vlans = (iface.tagged_vlans or vlans) %}
 no switchport trunk native vlan
{% endif %}
 switchport trunk allowed vlan {{ iface_vlans | map(attribute='vid') | compact_numlist }}

{# we don’t support any other mode #}
{%+ else %}

{% endif %}

{# store management address and gateway for later #}
{%- if iface.mgmt_only and iface.ip_addresses %}
{% set mgmt.ip = iface.ip_addresses[0].address %}
{% if iface.custom_fields.gateway %}
{% set mgmt.gw = iface.custom_fields.gateway.address %}
{% endif %}
{% endif %}

{% if iface.name in ifaces_dhcp | default([]) %}
 ip dhcp snooping trust
{% else %}
 no ip dhcp snooping trust
{% endif %}
{% endfor %}

{# management VLAN #}
{%- if mgmt.ip %}
interface Vlan1
 ip address {{ mgmt.ip | ipaddr('address') }} {{ mgmt.ip | ipaddr('netmask') }}
{% endif %}

voice vlan mac-address 2C-3E-CF-00-00-00 FF-FF-FF-00-00-00 description Cisco
voice vlan mac-address 3C-0E-23-00-00-00 FF-FF-FF-00-00-00 description Cisco
voice vlan mac-address B8-38-61-00-00-00 FF-FF-FF-00-00-00 description Cisco
voice vlan mac-address C4-14-3C-00-00-00 FF-FF-FF-00-00-00 description Cisco

{% if voice_vlan is defined %}
voice vlan {{ voice_vlan }}
{% else %}
no voice vlan
{% endif %}

snmp-server
snmp-server name {{ inventory_hostname }}
snmp-server location {{ rack }}
{# SNMP engine ID must be exactly 24 hex digits #}
snmp-server engineID local {{ snmp_engine_id }}
snmp-server group public v3  priv read CommunityView

sntp enable
{% for address in ntp %}
sntp server {{ address }}
{% endfor %}

ntp access-group default nomodify noquery

{% if ifaces_dhcp | default(false) %}
ip dhcp snooping
{% else %}
no ip dhcp snooping
{% endif %}

{% if mgmt.gw %}
ip route 0.0.0.0 0.0.0.0 {{ mgmt.gw | ipaddr('address') }} primary
{% endif %}

no ddp