Compare commits

..

No commits in common. "82b10e8133ccf4887ea038d0bec6ba77796dbbdc" and "bb41d406f8491e89691595bb7bd3cfe7f2fcd1d1" have entirely different histories.

8 changed files with 48 additions and 85 deletions

View file

@ -1,14 +0,0 @@
#!/usr/bin/python
class FilterModule(object):
'''Helper filters to make Ansible less unpleasant'''
def filters(self):
return {
'list2dict': self.list2dict,
}
def list2dict(self, items, key):
'''
Like items2dict but keep entire dictionaries as values.
'''
return {item[key]: item for item in items}

View file

@ -13,4 +13,3 @@ query_filters:
- role: 'compute-node' - role: 'compute-node'
- role: 'firewall' - role: 'firewall'
- role: 'switch' - role: 'switch'
- role: 'server'

View file

@ -0,0 +1,18 @@
#!/bin/sh
class="${1}"
name="${2}"
state="${3}"
case "${state}" in
"MASTER" | "FAULT")
systemctl start "${name}"
;;
"BACKUP" | "STOP")
systemctl stop "${name}"
;;
*)
logger "keepalived unknown state for ${name}: ${state}"
exit 1
;;
esac

View file

@ -1,17 +1,16 @@
# TODO rewrite task and templates into something sane once the old DHCP server is retired
- set_fact:
dhcp_servers: '{{ prefixes | selectattr("custom_fields.dhcp_server") | groupby(attribute="custom_fields.dhcp_server.address") }}'
- name: Install keepalived - name: Install keepalived
import_tasks: keepalived.yml import_tasks: keepalived.yml
- name: Create keepalive notify script for systemd services
copy:
dest: /usr/local/bin/
src: keepalive-service
mode: 0755
- name: Configure DHCP relays - name: Configure DHCP relays
template: template:
dest: '/etc/default/isc-dhcp-relay-{{ prefixes | selectattr("prefix", "==", item.0 | ipaddr("network/prefix")) | map(attribute="vrf.name") | first }}' dest: "/etc/default/isc-dhcp-relay"
src: isc-dhcp-relay.j2 src: isc-dhcp-relay.j2
loop: '{{ dhcp_servers }}'
loop_control:
label: "{{ item.0 }}"
notify: restart keepalived notify: restart keepalived
- name: Set up keepalived - name: Set up keepalived

View file

@ -3,7 +3,7 @@
| selectattr('role') | selectattr('role.value', '==', 'loopback') | selectattr('role') | selectattr('role.value', '==', 'loopback')
| map(attribute='address') %} | map(attribute='address') %}
{% set inside_vrfs = interfaces | selectattr('parent') | selectattr('parent.name', '==', 'bridge') {% set inside_vrfs = interfaces | selectattr('parent') | selectattr('parent.name', '==', 'bridge')
| selectattr('vrf') | map(attribute='vrf.name') | reject('==', 'outside') | sort %} | selectattr('vrf') | map(attribute='vrf') | rejectattr('name', '==', 'outside') -%}
frr defaults datacenter frr defaults datacenter
log syslog informational log syslog informational
@ -158,7 +158,7 @@ router bgp {{ asn.asn }} vrf inside
redistribute connected route-map loopback-inside redistribute connected route-map loopback-inside
{% for vrf in inside_vrfs %} {% for vrf in inside_vrfs %}
import vrf {{ vrf }} import vrf {{ vrf.name }}
{% endfor %} {% endfor %}
import vrf default import vrf default
import vrf route-map inside-import import vrf route-map inside-import
@ -180,14 +180,14 @@ router bgp {{ asn.asn }} vrf inside
redistribute connected route-map loopback-inside redistribute connected route-map loopback-inside
{% for vrf in inside_vrfs %} {% for vrf in inside_vrfs %}
import vrf {{ vrf }} import vrf {{ vrf.name }}
{% endfor %} {% endfor %}
import vrf default import vrf default
import vrf route-map inside-import import vrf route-map inside-import
exit-address-family exit-address-family
{% for vrf in vrfs.values() | selectattr('name', 'in', inside_vrfs) %} {% for vrf in inside_vrfs %}
# VRF for L2 network {{ vrf.name }}. Imports gateway from inside VRF. # VRF for L2 network {{ vrf.name }}. Imports gateway from inside VRF.
router bgp {{ asn.asn }} vrf {{ vrf.name }} router bgp {{ asn.asn }} vrf {{ vrf.name }}
bgp bestpath as-path multipath-relax bgp bestpath as-path multipath-relax
@ -195,27 +195,13 @@ router bgp {{ asn.asn }} vrf {{ vrf.name }}
address-family ipv4 unicast address-family ipv4 unicast
redistribute connected redistribute connected
import vrf inside import vrf inside
{% if vrf.custom_fields.imports %}
{% for import in vrf.custom_fields.imports %}
import vrf {{ import.name }}
{% endfor %}
import vrf route-map {{ vrf.name }}-import
{% else %}
import vrf route-map office-import import vrf route-map office-import
{% endif %}
exit-address-family exit-address-family
address-family ipv6 unicast address-family ipv6 unicast
redistribute connected redistribute connected
import vrf inside import vrf inside
{% if vrf.custom_fields.imports %}
{% for import in vrf.custom_fields.imports %}
import vrf {{ import.name }}
{% endfor %}
import vrf route-map {{ vrf.name }}-import
{% else %}
import vrf route-map office-import import vrf route-map office-import
{% endif %}
exit-address-family exit-address-family
{% endfor %} {% endfor %}
@ -227,8 +213,8 @@ ipv6 prefix-list default permit ::/0
ip prefix-list fabric permit 10.34.0.0/24 ge 32 ip prefix-list fabric permit 10.34.0.0/24 ge 32
ipv6 prefix-list fabric permit 2001:1470:fffd:3400::/64 ge 128 ipv6 prefix-list fabric permit 2001:1470:fffd:3400::/64 ge 128
# common prefix list for all inside networks {% for prefix in vrf_prefixes
{% for prefix in vrf_prefixes | selectattr('vrf.name', 'in', inside_vrfs) | selectattr('vrf.id', 'in', inside_vrfs|map(attribute='id'))
| sort(attribute='family.value') | sort(attribute='vlan.vid') %} | sort(attribute='family.value') | sort(attribute='vlan.vid') %}
{% if prefix.family.value == 4 %} {% if prefix.family.value == 4 %}
ip prefix-list office permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr('prefix') }} ip prefix-list office permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr('prefix') }}
@ -237,16 +223,6 @@ ipv6 prefix-list office permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr(
{% endif %} {% endif %}
{% endfor %} {% endfor %}
# individual prefix lists for each inside network
{% for prefix in vrf_prefixes | selectattr('vrf.name', 'in', inside_vrfs)
| sort(attribute='family.value') | sort(attribute='vlan.vid') %}
{% if prefix.family.value == 4 %}
ip prefix-list {{ prefix.vrf.name }} permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr('prefix') }}
{% else %}
ipv6 prefix-list {{ prefix.vrf.name }} permit {{ prefix.prefix }} ge {{ prefix.prefix | ipaddr('prefix') }}
{% endif %}
{% endfor %}
{% if wg_net is defined %} {% if wg_net is defined %}
ip prefix-list vpn permit {{ wg_net | ipaddr('subnet') }} ip prefix-list vpn permit {{ wg_net | ipaddr('subnet') }}
{% endif %} {% endif %}
@ -302,20 +278,6 @@ route-map inside-import permit 20
route-map inside-import permit 21 route-map inside-import permit 21
match ipv6 address prefix-list office match ipv6 address prefix-list office
{% for vrf in vrfs.values() | selectattr('custom_fields.imports') %}
route-map {{ vrf.name }}-import permit 10
match ip address prefix-list default
route-map {{ vrf.name }}-import permit 11
match ipv6 address prefix-list default
{% for import in vrf.custom_fields.imports %}
route-map {{ vrf.name }}-import permit {{ 100 + 10*loop.index0 }}
match ip address prefix-list {{ import.name }}
route-map {{ vrf.name }}-import permit {{ 101 + 10*loop.index0 }}
match ipv6 address prefix-list {{ import.name }}
{% endfor %}
{% endfor %}
# Route maps for advertised and received routes. # Route maps for advertised and received routes.
# Default VRF ↔ fabric. # Default VRF ↔ fabric.
route-map default->fabric permit 10 route-map default->fabric permit 10

View file

@ -1,12 +1,17 @@
{% set my_server = item.0 %} {% set dhcp_vlans = vrf_prefixes | selectattr('custom_fields.dhcp_ranges')
{% set my_vlans = item.1 | map(attribute='vlan.vid') | sort %} | map(attribute='vlan.vid') | sort -%}
{% set my_prefix = prefixes | selectattr("prefix", "==", my_server | ipaddr("network/prefix")) | first -%}
SERVERS="{{ my_server | ipaddr('address') }}" # What servers should the DHCP relay forward requests to?
{% if my_prefix.vrf.name == 'outside' %} SERVERS="{{ dhcp }}"
INTF_CMD="{{ my_vlans | map('regex_replace', '^', '-id bridge.') | join(' ') }} -iu {{ iface_uplink }} -iu peerlink.4 -U {{ my_prefix.vrf.name }}"
OPTIONS="" # On what interfaces should the DHCP relay (dhrelay) serve DHCP requests?
{% else %} # Always include the interface towards the DHCP server.
INTF_CMD="{{ my_vlans | map('regex_replace', '^', '-id bridge.') | join(' ') }} -U bridge.{{ my_prefix.vlan.vid }}" # This variable requires a -i for each interface configured above.
OPTIONS="--giaddr-src" # This will be used in the actual dhcrelay command
{% endif %} # For example, "-i eth0 -i eth1"
INTF_CMD="{{ interfaces | selectattr('parent') | selectattr('parent.name', '==', 'bridge')
| selectattr('untagged_vlan') | selectattr('untagged_vlan.vid', 'in', dhcp_vlans)
| map(attribute='name') | sort | map('regex_replace', '^', '-id ') | join(' ') }} -iu {{ iface_uplink }} -iu peerlink.4"
# Additional options that are passed to the DHCP relay daemon?
OPTIONS="-U outside"

View file

@ -1,5 +1,3 @@
{% set dhcrelays = prefixes | selectattr('prefix', 'in', dhcp_servers | map('first') | ipaddr("network/prefix"))
| map(attribute="vrf.name") | map('regex_replace', '^', 'dhcrelay@') %}
{% set exits = [inventory_hostname, peer]|sort -%} {% set exits = [inventory_hostname, peer]|sort -%}
global_defs { global_defs {
@ -20,8 +18,5 @@ vrrp_instance dhcrelay {
@^{{ exit }} {{ "169.254.1.0/24" | ipaddr(loop.index + 1) | ipaddr('address') }} @^{{ exit }} {{ "169.254.1.0/24" | ipaddr(loop.index + 1) | ipaddr('address') }}
{% endfor %} {% endfor %}
} }
notify_master "systemctl start {{ dhcrelays | join(' ') }}" notify /usr/local/bin/keepalive-service
notify_fault "systemctl start {{ dhcrelays | join(' ') }}"
notify_backup "systemctl stop {{ dhcrelays | join(' ') }}"
notify_stop "systemctl stop {{ dhcrelays | join(' ') }}"
} }

View file

@ -3,7 +3,6 @@
set_fact: set_fact:
vlans: '{{ query("netbox.netbox.nb_lookup", "vlans", api_filter="group=new-net", raw_data=true) vlans: '{{ query("netbox.netbox.nb_lookup", "vlans", api_filter="group=new-net", raw_data=true)
| sort(attribute="vid") }}' | sort(attribute="vid") }}'
vrfs: '{{ query("netbox.netbox.nb_lookup", "vrfs", raw_data=true) | list2dict("name") }}'
prefixes: '{{ query("netbox.netbox.nb_lookup", "prefixes", raw_data=true) prefixes: '{{ query("netbox.netbox.nb_lookup", "prefixes", raw_data=true)
| sort(attribute="prefix") | sort(attribute="family.value") }}' | sort(attribute="prefix") | sort(attribute="family.value") }}'