{% macro systemsection(device,root_pw,users,syslog_servers,ntp_servers) %} system { host-name {{ device.hostname }}; root-authentication { encrypted-password "{{ root_pw }}"; ## Client Higher } login { class sysadmin { permissions [ admin clear configure control firewall-control interface interface-control network reset rollback routing routing-control snmp snmp-control trace-control view view-configuration ]; } {% for user, details in users|dictsort %} user {{ user }} { uid 200{{ loop.index }}; class {{ details['role'] }}; authentication { encrypted-password "{{ details['password'] }}"; ## SECRET-DATA } } {% endfor %} } services { ssh; } syslog { {% for server in syslog_servers %} host {{ server }} { any notice; authorization info; } {% endfor %} file interactive-commands { interactive-commands any; } file linkupdown { any info; match "LINK_DOWN|LINK_UP"; } file messages { any notice; authorization info; } } {% if ntp_servers|length > 0 %} ntp { {% for server in ntp_servers %} server {{ server }}; {% endfor %} } {% endif %} } {%- endmacro %} {% macro chassissection(device,breakout_ports) %} chassis { aggregated-devices { ethernet { device-count {{ device.interfaces.all()|selectattr('type','eq','lag')|list|count }}; } } {% if breakout_ports %} {% for fpc, fpcdata in breakout_ports.items() %} fpc {{ fpc }} { {% for pic, picdata in fpcdata.items() %} pic {{ pic }} { {% for port, speed in picdata.items() %} port {{ port }} { channel-speed {{ speed }}; } {% endfor %} } {% endfor %} } {% endfor %} {% endif %} } {%- endmacro %} {% macro interfaceconfig(interface,rack = None) %} {{ interface.name }} { {% if interface.description != '' %} description "{{ interface.description }}"; {% endif %} {% if interface.mtu and not interface.lag %} mtu {{ interface.mtu }}; {% endif %} {% if interface.lag %} ether-options { 802.3ad {{ interface.lag.name }}; } {% endif %} {% if interface.name.startswith('ae') %} {% if interface.custom_field_data['esi_lag'] %} esi { auto-derive { lacp; } all-active; } {% endif %} aggregated-ether-options { lacp { periodic fast; {% if interface.custom_field_data['system_id'] %} system-id {{ interface.custom_field_data['system_id'] }}; {% elif interface.custom_field_data['esi_lag'] %} system-id 00:00:{{ '%02d' % rack|int }}:{% if interface.name[2:]|int < 99 %}{{ '%02d' % interface.name[2:]|int }}{% else %}{{ '%02x' % interface.name[2:]|int }}{% endif %}:00:01; {% endif %} } } {% endif %} {% if interface.ip_addresses.count() > 0 %} unit 0 { family inet { {% if interface.ip_addresses.first().status == 'reserved' %}inactive: {% endif %}address {{ interface.ip_addresses.first().address }}; } } {% endif %} {% if interface.mode != '' %} unit 0 { family ethernet-switching { {% if interface.mode=='ACCESS' %} interface-mode access; vlan { members {{ interface.untagged_vlan.vid }}; } {% elif interface.mode=='TAGGED' %} interface-mode trunk; vlan { members [ {% for vlan in interface.tagged_vlans %}{{ vlan.vid }} {% endfor %}]; } {% elif interface.mode=='TAGGED_ALL' %} interface-mode trunk; vlan { members [ all ]; } {% endif %} storm-control default; } } {% endif %} } {%- endmacro %} {% macro interfacesection(device,vlans) %} interfaces { {# Physical interfaces should be sorted by FPC/PIC/Port value - that's a challenge to do in Jinja so we cheat for now by putting the xe- interfaces first. This won't work for all devices! #} {% for interface in device.interfaces.filter(name__startswith='xe-') %} {{ interfaceconfig(interface) }} {% endfor %} {% for interface in device.interfaces.filter(name__startswith='et-') %} {{ interfaceconfig(interface) }} {% endfor %} {% for interface in device.interfaces.filter(name__startswith='ae') %} {{ interfaceconfig(interface,device.rack.name[5:]) }} {% endfor %} {% for interface in device.interfaces.filter(name__exact='em0') %} {{ interfaceconfig(interface) }} {% endfor %} {% for interface in device.interfaces.filter(name__startswith='irb') %} {% if loop.first %} irb { {% endif %} unit {{ interface.name[4:] }} { description "{{ interface.description }}"; family inet { {% if interface.ip_addresses.first().status == 'reserved' %}inactive: {% endif %}address {{ interface.ip_addresses.first().address }}; } } {% if loop.last %} } {% endif %} {% endfor %} {% for interface in device.interfaces.filter(name__startswith='lo') %} {{ interfaceconfig(interface) }} {% endfor %} } {%- endmacro %} {% macro snmpsection(rack, snmp) %} snmp { location "Domicilium Datacentre {{ rack['name'] }}"; contact "{{ snmp['contact'] }}"; community {{ snmp['community'] }} { authorization read-only; {% for client in snmp['clients'] %} {% if loop.first %} clients { {% endif %} {{ client }}; {% if loop.last %} } {% endif %} {% endfor %} } } {%- endmacro %} {% macro routingoptionssection(device, overlay_as, gateway) %} routing-options { router-id {{ device.primary_ip4.address.ip }}; autonomous-system {{ overlay_as }}; {% if gateway %} static { route 0.0.0.0/0 next-hop {{ gateway }}; } {% endif %} forwarding-table { export PFE-ECMP; chained-composite-next-hop { ingress { evpn; } } } } {%- endmacro %} {% macro bgprrmeshgroup(device,spines) %} group OVERLAY_RR_MESH { type internal; family evpn { signaling; } bfd-liveness-detection { minimum-interval 350; multiplier 3; session-mode automatic; } {% for dst_switch in spines if dst_switch.primary_ip4.address != device.primary_ip4.address %} neighbor {{ dst_switch.primary_ip4.address.ip }}; {% endfor %} } {%- endmacro %} {% macro bgpoverlaygroup(device) %} group OVERLAY { type internal; local-address {{ device.primary_ip4.address.ip }}; family evpn { signaling; } {% if device.role.name == 'Spine' %} cluster {{ device.primary_ip4.address.ip }}; multipath; {% endif %} bfd-liveness-detection { minimum-interval 350; multiplier 3; session-mode automatic; } {% for interface in device.interfaces.filter(cable__isnull=False) %} neighbor {{ interface.connected_endpoints[0].device.primary_ip4.address.ip }}; {% endfor %} } {%- endmacro %} {% macro bgpunderlaygroup(device) %} group UNDERLAY { type external; hold-time 10; family inet { unicast; } export BGP_LOOPBACK0; local-as {{ device.local_context_data['underlay_as'] }}; multipath { multiple-as; } {% for interface in device.interfaces.filter(cable__isnull=False) %} neighbor {{ interface.connected_endpoints[0].ip_addresses.first().address.ip }} { peer-as {{ interface.connected_endpoints[0].device.local_context_data['underlay_as'] }}; } {% endfor %} } {%- endmacro %} {% macro bgpsection(device,spines) %} {% if device.role.name in ['Spine','Lab-Spine'] %} {% set role='Spine' %} {% set other_role='Leaf' %} {% else %} {% set role='Leaf' %} {% set other_role='Spine' %} {% endif %} {% set name=device.name %} bgp { {{ bgpoverlaygroup(device) }} {% if role == 'Spine' %} {{ bgprrmeshgroup(device,spines) }} {% endif %} {{ bgpunderlaygroup(device) }} log-updown; } {%- endmacro %} {% macro sflowsection(sflow) %} sflow { {% for collector in sflow['collectors'] %} collector {{ collector }}; {% endfor %} {% for interface in sflow['interfaces'] %} interfaces {{ interface }}.0; {% endfor %} } {%- endmacro %} {% macro vlanssection(vlans,device) %} vlans { {# This next line selects all of the VLANs which are configured on this device #} {% for vlan in vlans if (device.interfaces.all()|selectattr('untagged_vlan.vid','equalto',vlan)|list|count or interfaces|map(attribute='tagged_vlans')|sum(start=[])|selectattr('vid','equalto',vlan)|list|count) or device.interfaces.all()|selectattr('name', 'equalto', 'irb.'+vlan.vid|string)|list|count %} vl{{ vlan.vid }} { {% if vlan.name != '' %} description "{{ vlan.name }}"; {% endif %} vlan-id {{ vlan.vid }}; {% if device.interfaces.all()|selectattr('name', 'equalto', 'irb.'+vlan.vid|string)|list|count %} l3-interface irb.{{vlan.vid}}; {% endif %} vxlan { vni {{ vlan.vid }}; } } {% endfor %} } {%- endmacro %}