From 2443a90bc58a3fdf36f00fd0ab0410f5b992338a Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Sun, 14 Apr 2024 15:09:48 +0200 Subject: [PATCH 01/10] fabric: use FHRP groups for virtual router IPs More realistic- and supported-like and also avoids duplicated gateway addresses. --- roles/fabric/templates/switch.intf.j2 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/roles/fabric/templates/switch.intf.j2 b/roles/fabric/templates/switch.intf.j2 index dfe633c..977c091 100644 --- a/roles/fabric/templates/switch.intf.j2 +++ b/roles/fabric/templates/switch.intf.j2 @@ -1,3 +1,6 @@ +{% set fhrp_assignments = query('netbox.netbox.nb_lookup', 'fhrp-group-assignments', raw_data=true) %} +{% set fhrp_groups = query('netbox.netbox.nb_lookup', 'fhrp-groups', raw_data=true) -%} + {% for iface in interfaces | rejectattr('name', 'in', ('lo', 'bridge')) | rejectattr('mgmt_only') | selectattr('enabled') %} auto {{ iface.name }} iface {{ iface.name }} @@ -37,13 +40,13 @@ iface {{ iface.name }} {% endif %} {#- Addresses. #} -{% for addr in iface.ip_addresses | rejectattr('role') %} +{% for addr in iface.ip_addresses %} address {{ addr.address }} {% endfor %} -{% set anycast = iface.ip_addresses | selectattr('role') | selectattr('role.value', '==', 'anycast') - | map(attribute='address') %} -{% if anycast %} - address-virtual 00:00:5e:00:01:01 {{ anycast | ipaddr(1) | join(' ') }} +{% if iface.count_fhrp_groups > 0 %} +{% set fhrp_assignment = fhrp_assignments | selectattr('interface.id', '==', iface.id) | first %} +{% set fhrp_group = fhrp_groups | selectattr('id', '==', fhrp_assignment.group.id) | first %} + address-virtual 00:00:5e:00:01:01 {{ fhrp_group.ip_addresses | sort(attribute='family') | map(attribute='address') | join(' ') }} {% endif %} {% endfor %} From c07c03a430c12d41c6a506fffb80dfc5d64cae69 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Sat, 27 Apr 2024 10:58:55 +0200 Subject: [PATCH 02/10] Set default inventory --- README.md | 4 ++-- ansible.cfg | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b1dfa86..765a04a 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ Create a read-only token in NetBox. Set variables required to access NetBox: Run one-off tasks with (add `--key-file` or other options as necessary): - ansible -i inventory.yml -m ping 'spine-*' + ansible -m ping 'spine-*' Run a playbook with: - ansible-playbook setup.yml -i inventory.yml -l 'spine-*' + ansible-playbook setup.yml -l 'spine-*' ## NetBox data diff --git a/ansible.cfg b/ansible.cfg index 7925ec3..aa4a4a6 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,5 +1,6 @@ [defaults] nocows = true +filter_plugins = filter_plugins +inventory = inventory.yml remote_user = root vault_identity = network -filter_plugins = filter_plugins From 1c0709a6a6b32984f324f6fc8b0de9af26e8ddd0 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Sat, 27 Apr 2024 11:30:20 +0200 Subject: [PATCH 03/10] fabric: allow all VLANs on bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t try to guess what should be allowed because not all switch links are tagged in NetBox. For now we limit mainly on access switches. --- roles/fabric/templates/bridge.intf.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/fabric/templates/bridge.intf.j2 b/roles/fabric/templates/bridge.intf.j2 index af9ae63..0e3d4fe 100644 --- a/roles/fabric/templates/bridge.intf.j2 +++ b/roles/fabric/templates/bridge.intf.j2 @@ -3,7 +3,7 @@ {# interfaces that belong to this bridge #} {% set ports = interfaces | selectattr('enabled') | selectattr('bridge') | selectattr('bridge.name', '==', bridge.name) %} {# allowed VLANs can be specified on the bridge, any of its ports, or all VLANs in NetBox #} -{% set my_vlans = bridge.tagged_vlans or (ports | iface_vlans | flatten | sort(attribute='vid') | unique) or vlans %} +{% set my_vlans = bridge.tagged_vlans or vlans %} {% set my_vlan_ids = my_vlans | map(attribute='vid') | sort -%} auto {{ bridge.name }} From 457ab7d3b7203127dce7cdb6c4a5c7054f389200 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Sun, 28 Apr 2024 10:59:32 +0200 Subject: [PATCH 04/10] Query prefixes once for all hosts And group them into vrf_prefixes for VLAN networks and bgp_prefixes for servers plugged directly into fabric. This should reduce the number of queries to NetBox when configuring firewalls and exit switches. Not sure but I think set_fact helps to avoid queries (as opposed to setting group_vars). --- group_vars/all/vars.yml | 1 - roles/exit/templates/frr.conf.j2 | 16 +++++++------- roles/exit/templates/isc-dhcp-relay.j2 | 6 +++--- roles/facts/tasks/main.yml | 16 ++++++++++++++ roles/firewall/templates/frr.conf.j2 | 7 ++----- roles/firewall/templates/networks.nft.j2 | 21 ++++++------------- roles/firewall/templates/nftables.nft.j2 | 8 +++---- .../templates/networks.json.j2 | 11 ++++------ roles/leaf/templates/frr.conf.j2 | 9 +++----- setup.yml | 7 +++++++ 10 files changed, 52 insertions(+), 50 deletions(-) delete mode 100644 group_vars/all/vars.yml create mode 100644 roles/facts/tasks/main.yml diff --git a/group_vars/all/vars.yml b/group_vars/all/vars.yml deleted file mode 100644 index 0b73a21..0000000 --- a/group_vars/all/vars.yml +++ /dev/null @@ -1 +0,0 @@ -vlans: "{{ query('netbox.netbox.nb_lookup', 'vlans', api_filter='group=new-net', raw_data=true) | sort(attribute='vid') }}" diff --git a/roles/exit/templates/frr.conf.j2 b/roles/exit/templates/frr.conf.j2 index cd18add..ed10bbf 100644 --- a/roles/exit/templates/frr.conf.j2 +++ b/roles/exit/templates/frr.conf.j2 @@ -213,17 +213,15 @@ ipv6 prefix-list default permit ::/0 ip prefix-list fabric permit 10.34.0.0/24 ge 32 ipv6 prefix-list fabric permit 2001:1470:fffd:3400::/64 ge 128 -{% for vrf in inside_vrfs %} -{% set prefixes = query('netbox.netbox.nb_lookup', 'prefixes', api_filter='vrf_id='~vrf.id, raw_data=true) - | sort(attribute='family.value') %} -{% for prefix in prefixes %} +{% for prefix in vrf_prefixes + | selectattr('vrf.id', 'in', inside_vrfs|map(attribute='id')) + | sort(attribute='family.value') | sort(attribute='vlan.vid') %} {% if prefix.family.value == 4 %} ip prefix-list office permit {{ prefix.prefix }} ge 24 {% else %} ipv6 prefix-list office permit {{ prefix.prefix }} ge 64 {% endif %} {% endfor %} -{% endfor %} {% if wg_net is defined %} ip prefix-list vpn permit {{ wg_net | ipaddr('subnet') }} @@ -237,7 +235,7 @@ ip prefix-list nat permit {{ wg_ip | ipaddr('host') }} ip prefix-list nat permit {{ network }} {% endfor %} -{% for prefix in query('netbox.netbox.nb_lookup', 'prefixes', raw_data=true, api_filter='role=bgp') | selectattr('tenant') %} +{% for prefix in bgp_prefixes | sort(attribute='family.value') %} {% if prefix.family.value == 4 %} ip prefix-list dc permit {{ prefix.prefix }} ge 32 {% else %} @@ -281,7 +279,7 @@ route-map inside-import permit 21 match ipv6 address prefix-list office # Route maps for advertised and received routes. -# Inside ↔ fabric. +# Default VRF ↔ fabric. route-map default->fabric permit 10 match ip address prefix-list default route-map default->fabric permit 11 @@ -296,7 +294,7 @@ route-map fabric->default permit 20 route-map fabric->default permit 21 match ipv6 address prefix-list dc -# Inside ↔ firewall. +# Inside VRF ↔ firewall. route-map inside->firewall permit 1 match interface lo route-map inside->firewall permit 20 @@ -313,7 +311,7 @@ route-map firewall->inside permit 10 route-map firewall->inside permit 11 match ipv6 address prefix-list default -# Outside ↔ firewall. +# Outside VRF ↔ firewall. route-map outside->firewall permit 10 match ip address prefix-list default route-map outside->firewall permit 11 diff --git a/roles/exit/templates/isc-dhcp-relay.j2 b/roles/exit/templates/isc-dhcp-relay.j2 index 8e8c1fd..21cb999 100644 --- a/roles/exit/templates/isc-dhcp-relay.j2 +++ b/roles/exit/templates/isc-dhcp-relay.j2 @@ -1,5 +1,5 @@ -{% set dhcp_networks = query('netbox.netbox.nb_lookup', 'prefixes', api_filter='role=dhcp-pool', raw_data=true) - | selectattr('vlan') | map(attribute='vlan.vid') | sort -%} +{% set dhcp_vlans = vrf_prefixes | selectattr('custom_fields.dhcp_ranges') + | map(attribute='vlan.vid') | sort -%} # What servers should the DHCP relay forward requests to? SERVERS="{{ dhcp }}" @@ -10,7 +10,7 @@ SERVERS="{{ dhcp }}" # This will be used in the actual dhcrelay command # For example, "-i eth0 -i eth1" INTF_CMD="{{ interfaces | selectattr('parent') | selectattr('parent.name', '==', 'bridge') - | selectattr('untagged_vlan') | selectattr('untagged_vlan.vid', 'in', dhcp_networks) + | 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? diff --git a/roles/facts/tasks/main.yml b/roles/facts/tasks/main.yml new file mode 100644 index 0000000..568fe41 --- /dev/null +++ b/roles/facts/tasks/main.yml @@ -0,0 +1,16 @@ +# Make expensive lookups to NetBox once for later reference by any host. +- name: Lookup networks and prefixes + set_fact: + vlans: '{{ query("netbox.netbox.nb_lookup", "vlans", api_filter="group=new-net", raw_data=true) + | sort(attribute="vid") }}' + prefixes: '{{ query("netbox.netbox.nb_lookup", "prefixes", raw_data=true) + | sort(attribute="prefix") | sort(attribute="family.value") }}' + +- name: Select VLAN and BGP prefixes + set_fact: + vrf_prefixes: '{{ prefixes | selectattr("vrf") + | selectattr("vlan") | selectattr("vlan.id", "in", vlans|map(attribute="id")) + | sort(attribute="vlan.vid") }}' + bgp_prefixes: '{{ prefixes | selectattr("tenant") + | selectattr("role") | selectattr("role.slug", "==", "bgp") + | sort(attribute="tenant.slug") }}' diff --git a/roles/firewall/templates/frr.conf.j2 b/roles/firewall/templates/frr.conf.j2 index 1329092..324ec23 100644 --- a/roles/firewall/templates/frr.conf.j2 +++ b/roles/firewall/templates/frr.conf.j2 @@ -82,16 +82,13 @@ ipv6 prefix-list default permit ::/0 ip prefix-list fabric permit 10.34.0.0/24 ge 32 -{% for vlan in vlans %} -{% for prefix in query('netbox.netbox.nb_lookup', 'prefixes', api_filter='vlan_id='~vlan.id, raw_data=true) %} -{% if prefix.vrf and prefix.vrf.name != 'outside' %} +{% for prefix in vrf_prefixes | rejectattr('vrf.name', '==', 'outside') + | sort(attribute='family.value') %} {% if prefix.family.value == 4 %} ip prefix-list office permit {{ prefix.prefix }} ge 24 {% elif prefix.family.value == 6 %} ipv6 prefix-list office permit {{ prefix.prefix }} ge 64 {% endif %} -{% endif %} -{% endfor %} {% endfor %} {% if wg_net is defined %} diff --git a/roles/firewall/templates/networks.nft.j2 b/roles/firewall/templates/networks.nft.j2 index 2a13f6e..cb74b20 100644 --- a/roles/firewall/templates/networks.nft.j2 +++ b/roles/firewall/templates/networks.nft.j2 @@ -1,18 +1,9 @@ -{% for vlan in vlans %} -{% set prefixes = query('netbox.netbox.nb_lookup', 'prefixes', api_filter='vlan_id='~vlan.id, raw_data=true) %} -{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map(attribute='prefix') %} -{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map(attribute='prefix') %} -set {{ vlan.name }} { - type ipv4_addr; flags interval -{% if prefixes4 %} - elements = { {{ prefixes4 | join(', ') }} } -{% endif %} -} -set {{ vlan.name }}/6 { - type ipv6_addr; flags interval -{% if prefixes6 %} - elements = { {{ prefixes6 | join(', ') }} } -{% endif %} +{% for family, family_prefixes in vrf_prefixes | groupby('family.value') %} +{% for vlan, vlan_prefixes in family_prefixes | groupby('vlan.vid') %} +set {{ vlan_prefixes[0].vlan.name }}{% if family == 6 %}/6{% endif %} { + type ipv{{ family }}_addr; flags interval + elements = { {{ vlan_prefixes | map(attribute='prefix') | join(',') }} } } +{% endfor %} {% endfor %} diff --git a/roles/firewall/templates/nftables.nft.j2 b/roles/firewall/templates/nftables.nft.j2 index d0b0892..ab1eab5 100644 --- a/roles/firewall/templates/nftables.nft.j2 +++ b/roles/firewall/templates/nftables.nft.j2 @@ -81,13 +81,13 @@ table inet filter { comment "Forward DNAT traffic for servers and suchlike" # Forward IPv4 to/from VPN users in the same network. -{% for vlan in vlans %} - iif @inside ip saddr @{{ vlan.name }} ip daddr @{{ vlan.name }} accept +{% for vlan in vrf_prefixes | selectattr('family.value', '==', 4) | map(attribute='vlan.name') | unique %} + iif @inside ip saddr @{{ vlan }} ip daddr @{{ vlan }} accept {% endfor %} # Forward IPv6 to/from VPN users in the same network. -{% for vlan in vlans %} - iif @inside ip6 saddr @{{ vlan.name }}/6 ip6 daddr @{{ vlan.name }}/6 accept +{% for vlan in vrf_prefixes | selectattr('family.value', '==', 6) | map(attribute='vlan.name') | unique %} + iif @inside ip6 saddr @{{ vlan }}/6 ip6 daddr @{{ vlan }}/6 accept {% endfor %} include "/etc/nftables.d/forward.nft*" diff --git a/roles/firewall_master/templates/networks.json.j2 b/roles/firewall_master/templates/networks.json.j2 index 1485db9..15e0905 100644 --- a/roles/firewall_master/templates/networks.json.j2 +++ b/roles/firewall_master/templates/networks.json.j2 @@ -1,11 +1,8 @@ -{% set prefixes = query('netbox.netbox.nb_lookup', 'prefixes', raw_data=true) -%} - { -{% for vlan in vlans %} -{% set vlan_prefixes = prefixes | selectattr('vlan') | selectattr('vlan.id', '==', vlan.id) | map(attribute='prefix') %} - "{{ vlan.name }}": { - "ip": {{ vlan_prefixes | ipv4 | to_json }}, - "ip6": {{ vlan_prefixes | ipv6 | to_json }} +{% for vlan, addrs in vrf_prefixes | groupby('vlan.vid') %} + "{{ addrs[0].vlan.name }}": { + "ip": {{ addrs | selectattr('family.value', '==', 4) | map(attribute='prefix') | to_json }}, + "ip6": {{ addrs | selectattr('family.value', '==', 6) | map(attribute='prefix') | to_json }} }{% if not loop.last %},{% endif +%} {% endfor %} } diff --git a/roles/leaf/templates/frr.conf.j2 b/roles/leaf/templates/frr.conf.j2 index 1b6f4d7..2510328 100644 --- a/roles/leaf/templates/frr.conf.j2 +++ b/roles/leaf/templates/frr.conf.j2 @@ -78,16 +78,13 @@ route-map loopbacks permit 10 ip prefix-list default permit 0.0.0.0/0 ipv6 prefix-list default permit ::/0 -{% for tenant in my_tenants %} -{% for prefix in query('netbox.netbox.nb_lookup', 'prefixes', raw_data=true, api_filter='tenant='~tenant) - | selectattr('role') | selectattr('role.slug', '==', 'bgp') | rejectattr('vlan') %} +{% for prefix in bgp_prefixes | selectattr('tenant.slug', 'in', my_tenants) %} {% if prefix.family.value == 4 %} -ip prefix-list dc-{{ tenant }} permit {{ prefix.prefix }} ge 32 +ip prefix-list dc-{{ prefix.tenant.slug }} permit {{ prefix.prefix }} ge 32 {% else %} -ipv6 prefix-list dc-{{ tenant }} permit {{ prefix.prefix }} ge 64 +ipv6 prefix-list dc-{{ prefix.tenant.slug }} permit {{ prefix.prefix }} ge 64 {% endif %} {% endfor %} -{% endfor %} # We only announce the default route to DC servers. route-map default->dc permit 10 diff --git a/setup.yml b/setup.yml index 660548c..e61dfb4 100644 --- a/setup.yml +++ b/setup.yml @@ -1,3 +1,8 @@ +- hosts: '*' + roles: + - facts + +# Set up fabric. - hosts: spine-* roles: - spine @@ -10,11 +15,13 @@ roles: - exit +# Set up access switches. - hosts: access-*, sw-* gather_facts: false roles: - access +# Set up firewall. - hosts: fw-* roles: - firewall From 8a9d47f1762df8e413a26ae72b72b8a9cf2ddc3e Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Sun, 28 Apr 2024 12:15:39 +0200 Subject: [PATCH 05/10] firewall: configure NAT from NetBox data This is dynamic NAT for (mostly) physical networks. NAT for custom prefixes can still be defined in the app. --- roles/firewall/templates/nftables.nft.j2 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/roles/firewall/templates/nftables.nft.j2 b/roles/firewall/templates/nftables.nft.j2 index ab1eab5..8535b70 100644 --- a/roles/firewall/templates/nftables.nft.j2 +++ b/roles/firewall/templates/nftables.nft.j2 @@ -108,12 +108,25 @@ table ip nat { map netmap-in { type ipv4_addr : interval ipv4_addr; flags interval; } map netmap-out { type ipv4_addr : interval ipv4_addr; flags interval; } + map nat { + type ipv4_addr : interval ipv4_addr; flags interval + elements = { +{% for prefix in vrf_prefixes | selectattr('family.value', '==', 4) | selectattr('custom_fields.nat') %} + {{ prefix.prefix }} : {{ prefix.custom_fields.nat.address | ipmath(0) }} + {{- '' if loop.last else ',' }} # {{ prefix.vlan.name }} +{% endfor %} + } + } + chain postrouting { type nat hook postrouting priority srcnat iif @inside oif @outside snat ip prefix to ip saddr map @netmap-out \ comment "Static source NAT for 1:1 mapped addresses" + iif @inside oif @outside snat to ip saddr map @nat \ + comment "Dynamic NAT for private IPv4 networks" + include "/etc/nftables.d/nat.nft*" } From 7656c05b2de0c7ae180a690af3892497431eea8f Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Tue, 30 Apr 2024 20:59:49 +0200 Subject: [PATCH 06/10] Revert "firewall: configure NAT from NetBox data" Changed my mind. All NAT and VPN is configured from the app now. --- roles/firewall/templates/nftables.nft.j2 | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/roles/firewall/templates/nftables.nft.j2 b/roles/firewall/templates/nftables.nft.j2 index 8535b70..ab1eab5 100644 --- a/roles/firewall/templates/nftables.nft.j2 +++ b/roles/firewall/templates/nftables.nft.j2 @@ -108,25 +108,12 @@ table ip nat { map netmap-in { type ipv4_addr : interval ipv4_addr; flags interval; } map netmap-out { type ipv4_addr : interval ipv4_addr; flags interval; } - map nat { - type ipv4_addr : interval ipv4_addr; flags interval - elements = { -{% for prefix in vrf_prefixes | selectattr('family.value', '==', 4) | selectattr('custom_fields.nat') %} - {{ prefix.prefix }} : {{ prefix.custom_fields.nat.address | ipmath(0) }} - {{- '' if loop.last else ',' }} # {{ prefix.vlan.name }} -{% endfor %} - } - } - chain postrouting { type nat hook postrouting priority srcnat iif @inside oif @outside snat ip prefix to ip saddr map @netmap-out \ comment "Static source NAT for 1:1 mapped addresses" - iif @inside oif @outside snat to ip saddr map @nat \ - comment "Dynamic NAT for private IPv4 networks" - include "/etc/nftables.d/nat.nft*" } From 8c82af23e4715d74b8f55439dc7263b7134b9def Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Fri, 3 May 2024 11:27:27 +0200 Subject: [PATCH 07/10] firewall: also configure VPN forwards in the app There we can define forwards only for networks with actual VPN users. --- roles/firewall/templates/nftables.nft.j2 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/roles/firewall/templates/nftables.nft.j2 b/roles/firewall/templates/nftables.nft.j2 index ab1eab5..acb7d29 100644 --- a/roles/firewall/templates/nftables.nft.j2 +++ b/roles/firewall/templates/nftables.nft.j2 @@ -80,16 +80,6 @@ table inet filter { ct status dnat accept \ comment "Forward DNAT traffic for servers and suchlike" - # Forward IPv4 to/from VPN users in the same network. -{% for vlan in vrf_prefixes | selectattr('family.value', '==', 4) | map(attribute='vlan.name') | unique %} - iif @inside ip saddr @{{ vlan }} ip daddr @{{ vlan }} accept -{% endfor %} - - # Forward IPv6 to/from VPN users in the same network. -{% for vlan in vrf_prefixes | selectattr('family.value', '==', 6) | map(attribute='vlan.name') | unique %} - iif @inside ip6 saddr @{{ vlan }}/6 ip6 daddr @{{ vlan }}/6 accept -{% endfor %} - include "/etc/nftables.d/forward.nft*" } From 16f34c4502e19303672bce92dd7e3db176953c4d Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Mon, 13 May 2024 17:39:05 +0200 Subject: [PATCH 08/10] =?UTF-8?q?Don=E2=80=99t=20gather=20facts=20when=20s?= =?UTF-8?q?etting=20them?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.yml b/setup.yml index e61dfb4..a8fc0ac 100644 --- a/setup.yml +++ b/setup.yml @@ -1,4 +1,5 @@ - hosts: '*' + gather_facts: false roles: - facts From 0e9dac6985c166a50407f2c02b8218fa4aeeba2b Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Mon, 13 May 2024 17:44:39 +0200 Subject: [PATCH 09/10] fabric: support arbitrary port breakouts Not that we use anything but 1x and 4x. Mainly done so I can drop nonexistent (because they have been broken out) interfaces from NetBox. --- roles/fabric/templates/ports.conf.j2 | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/roles/fabric/templates/ports.conf.j2 b/roles/fabric/templates/ports.conf.j2 index 907b97b..f52212a 100644 --- a/roles/fabric/templates/ports.conf.j2 +++ b/roles/fabric/templates/ports.conf.j2 @@ -1,11 +1,7 @@ # https://docs.nvidia.com/networking-ethernet-software/cumulus-linux/Layer-1-and-Switch-Ports/Interface-Configuration-and-Management/Switch-Port-Attributes/#breakout-ports -{% for interface in interfaces | selectattr('name', 'match', '^swp[0-9]+$') %} -{{ interface.name|regex_replace('^swp', '') }}= -{%- if interfaces|selectattr('name', 'match', '^'+interface.name+'s[0-9]+$') %} -4x -{% elif not interface.enabled %} -disabled -{% else %} -1x -{% endif %} +{% for interface in interfaces | selectattr('name', 'match', '^swp[0-9]+(s0)?$') %} +{# get '1' from 'swp1' and '2' from 'swp2s0' #} +{% set port = interface.name | regex_replace('^swp([0-9]+).*$', '\\1') %} +{% set count = interfaces | selectattr('name', 'match', '^swp'+port+'(s[0-9])*$') | length %} +{{ port }}={% if interface.enabled or count > 1 %}{{ count }}x{% else %}disabled{% endif +%} {% endfor %} From 668af8bdb6b21f3c77a0e287af35c6927c76da77 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Sun, 19 May 2024 10:09:37 +0200 Subject: [PATCH 10/10] firewall: use a handler to reboot --- roles/firewall/handlers/main.yml | 4 ++++ roles/firewall/tasks/mgmt.yml | 18 ++++-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/roles/firewall/handlers/main.yml b/roles/firewall/handlers/main.yml index 46bf0d7..d2beb3b 100644 --- a/roles/firewall/handlers/main.yml +++ b/roles/firewall/handlers/main.yml @@ -6,6 +6,10 @@ command: mkinitfs when: "'handler' not in ansible_skip_tags" +- name: reboot + reboot: + when: "'handler' not in ansible_skip_tags" + - name: reload frr command: /usr/lib/frr/frr-reload.py --reload /etc/frr/frr.conf when: "'handler' not in ansible_skip_tags" diff --git a/roles/firewall/tasks/mgmt.yml b/roles/firewall/tasks/mgmt.yml index bddee5e..8b5b976 100644 --- a/roles/firewall/tasks/mgmt.yml +++ b/roles/firewall/tasks/mgmt.yml @@ -3,23 +3,13 @@ dest: /etc/network/interfaces.d/mgmt.intf src: mgmt.intf.j2 mode: 0644 - register: task_mgmt_interface + notify: reboot - name: Run SSH in management VRF lineinfile: path: /etc/conf.d/sshd + regexp: "#* *vrf=" line: "vrf=\"mgmt\"" - register: task_ssh_vrf + notify: reboot -- name: Reboot for new VRF - reboot: - when: task_mgmt_interface.changed or task_ssh_vrf.changed - register: task_reboot - -- name: Reset the connection - meta: reset_connection - -- name: Wait for the network device to reload - wait_for_connection: - delay: 10 - when: task_reboot.changed +- meta: flush_handlers