Merge pull request #10048 from qlyoung/fix-reload-doc-comments

Fix reload comments
This commit is contained in:
Donatas Abraitis 2021-11-15 17:54:18 +02:00 committed by GitHub
commit fd7d888003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -172,7 +172,6 @@ class Vtysh(object):
class Context(object):
"""
A Context object represents a section of frr configuration such as:
!
@ -234,7 +233,6 @@ def get_normalized_mac_ip_line(line):
class Config(object):
"""
A frr configuration is stored in a Config object. A Config object
contains a dictionary of Context objects where the Context keys
@ -265,22 +263,20 @@ class Config(object):
if ":" in line:
line = get_normalized_mac_ip_line(line)
"""
vrf static routes can be added in two ways. The old way is:
"ip route x.x.x.x/x y.y.y.y vrf <vrfname>"
but it's rendered in the configuration as the new way::
vrf <vrf-name>
ip route x.x.x.x/x y.y.y.y
exit-vrf
this difference causes frr-reload to not consider them a
match and delete vrf static routes incorrectly.
fix the old way to match new "show running" output so a
proper match is found.
"""
# vrf static routes can be added in two ways. The old way is:
#
# "ip route x.x.x.x/x y.y.y.y vrf <vrfname>"
#
# but it's rendered in the configuration as the new way::
#
# vrf <vrf-name>
# ip route x.x.x.x/x y.y.y.y
# exit-vrf
#
# this difference causes frr-reload to not consider them a
# match and delete vrf static routes incorrectly.
# fix the old way to match new "show running" output so a
# proper match is found.
if (
line.startswith("ip route ") or line.startswith("ipv6 route ")
) and " vrf " in line:
@ -326,14 +322,12 @@ class Config(object):
"""
Return the lines read in from the configuration
"""
return "\n".join(self.lines)
def get_contexts(self):
"""
Return the parsed context as strings for display, log etc.
"""
for (_, ctx) in sorted(iteritems(self.contexts)):
print(str(ctx) + "\n")
@ -341,18 +335,15 @@ class Config(object):
"""
Save the provided key and lines as a context
"""
if not key:
return
"""
IP addresses specified in "network" statements, "ip prefix-lists"
etc. can differ in the host part of the specification the user
provides and what the running config displays. For example, user
can specify 11.1.1.1/24, and the running config displays this as
11.1.1.0/24. Ensure we don't do a needless operation for such
lines. IS-IS & OSPFv3 have no "network" support.
"""
# IP addresses specified in "network" statements, "ip prefix-lists"
# etc. can differ in the host part of the specification the user
# provides and what the running config displays. For example, user can
# specify 11.1.1.1/24, and the running config displays this as
# 11.1.1.0/24. Ensure we don't do a needless operation for such lines.
# IS-IS & OSPFv3 have no "network" support.
re_key_rt = re.match(r"(ip|ipv6)\s+route\s+([A-Fa-f:.0-9/]+)(.*)$", key[0])
if re_key_rt:
addr = re_key_rt.group(2)
@ -430,10 +421,8 @@ class Config(object):
newlines.append(line)
lines = newlines
"""
More fixups in user specification and what running config shows.
"null0" in routes must be replaced by Null0.
"""
# More fixups in user specification and what running config shows.
# "null0" in routes must be replaced by Null0.
if (
key[0].startswith("ip route")
or key[0].startswith("ipv6 route")
@ -441,10 +430,8 @@ class Config(object):
):
key[0] = re.sub(r"\s+null0(\s*$)", " Null0", key[0])
"""
Similar to above, but when the static is in a vrf, it turns into a
blackhole nexthop for both null0 and Null0. Fix it accordingly
"""
# Similar to above, but when the static is in a vrf, it turns into a
# blackhole nexthop for both null0 and Null0. Fix it accordingly
if lines and key[0].startswith("vrf "):
newlines = []
for line in lines:
@ -474,9 +461,7 @@ class Config(object):
def load_contexts(self):
"""
Parse the configuration and create contexts for each appropriate block
"""
"""
The end of a context is flagged via the 'end' keyword:
!
@ -520,25 +505,25 @@ router ospf
timers throttle spf 0 50 5000
!
end
The code assumes that its working on the output from the "vtysh -m"
command. That provides the appropriate markers to signify end of
a context. This routine uses that to build the contexts for the
config.
There are single line contexts such as "log file /media/node/zebra.log"
and multi-line contexts such as "router ospf" and subcontexts
within a context such as "address-family" within "router bgp"
In each of these cases, the first line of the context becomes the
key of the context. So "router bgp 10" is the key for the non-address
family part of bgp, "router bgp 10, address-family ipv6 unicast" is
the key for the subcontext and so on.
This dictionary contains a tree of all commands that we know start a
new multi-line context. All other commands are treated either as
commands inside a multi-line context or as single-line contexts. This
dictionary should be updated whenever a new node is added to FRR.
"""
# The code assumes that its working on the output from the "vtysh -m"
# command. That provides the appropriate markers to signify end of
# a context. This routine uses that to build the contexts for the
# config.
#
# There are single line contexts such as "log file /media/node/zebra.log"
# and multi-line contexts such as "router ospf" and subcontexts
# within a context such as "address-family" within "router bgp"
# In each of these cases, the first line of the context becomes the
# key of the context. So "router bgp 10" is the key for the non-address
# family part of bgp, "router bgp 10, address-family ipv6 unicast" is
# the key for the subcontext and so on.
# This dictionary contains a tree of all commands that we know start a
# new multi-line context. All other commands are treated either as
# commands inside a multi-line context or as single-line contexts. This
# dictionary should be updated whenever a new node is added to FRR.
ctx_keywords = {
"router bgp ": {
"address-family ": {
@ -788,16 +773,12 @@ def check_for_exit_vrf(lines_to_add, lines_to_del):
return (lines_to_add, lines_to_del)
"""
This method handles deletion of bgp peer group config.
The objective is to delete config lines related to peers
associated with the peer-group and move the peer-group
config line to the end of the lines_to_del list.
"""
def delete_move_lines(lines_to_add, lines_to_del):
"""
This function handles deletion of bgp peer group config. The objective is
to delete config lines related to peers associated with the peer-group and
move the peer-group config line to the end of the lines_to_del list.
"""
del_dict = dict()
# Stores the lines to move to the end of the pending list.
lines_to_del_to_del = []
@ -805,54 +786,51 @@ def delete_move_lines(lines_to_add, lines_to_del):
lines_to_del_to_app = []
found_pg_del_cmd = False
"""
When "neighbor <pg_name> peer-group" under a bgp instance is removed,
it also deletes the associated peer config. Any config line below no form of
peer-group related to a peer are errored out as the peer no longer exists.
To cleanup peer-group and associated peer(s) configs:
- Remove all the peers config lines from the pending list (lines_to_del list).
- Move peer-group deletion line to the end of the pending list, to allow
removal of any of the peer-group specific configs.
# When "neighbor <pg_name> peer-group" under a bgp instance is removed,
# it also deletes the associated peer config. Any config line below no form of
# peer-group related to a peer are errored out as the peer no longer exists.
# To cleanup peer-group and associated peer(s) configs:
# - Remove all the peers config lines from the pending list (lines_to_del list).
# - Move peer-group deletion line to the end of the pending list, to allow
# removal of any of the peer-group specific configs.
#
# Create a dictionary of config context (i.e. router bgp vrf x).
# Under each context node, create a dictionary of a peer-group name.
# Append a peer associated to the peer-group into a list under a peer-group node.
# Remove all of the peer associated config lines from the pending list.
# Append peer-group deletion line to end of the pending list.
#
# Example:
# neighbor underlay peer-group
# neighbor underlay remote-as external
# neighbor underlay advertisement-interval 0
# neighbor underlay timers 3 9
# neighbor underlay timers connect 10
# neighbor swp1 interface peer-group underlay
# neighbor swp1 advertisement-interval 0
# neighbor swp1 timers 3 9
# neighbor swp1 timers connect 10
# neighbor swp2 interface peer-group underlay
# neighbor swp2 advertisement-interval 0
# neighbor swp2 timers 3 9
# neighbor swp2 timers connect 10
# neighbor swp3 interface peer-group underlay
# neighbor uplink1 interface remote-as internal
# neighbor uplink1 advertisement-interval 0
# neighbor uplink1 timers 3 9
# neighbor uplink1 timers connect 10
Create a dictionary of config context (i.e. router bgp vrf x).
Under each context node, create a dictionary of a peer-group name.
Append a peer associated to the peer-group into a list under a peer-group node.
Remove all of the peer associated config lines from the pending list.
Append peer-group deletion line to end of the pending list.
Example:
neighbor underlay peer-group
neighbor underlay remote-as external
neighbor underlay advertisement-interval 0
neighbor underlay timers 3 9
neighbor underlay timers connect 10
neighbor swp1 interface peer-group underlay
neighbor swp1 advertisement-interval 0
neighbor swp1 timers 3 9
neighbor swp1 timers connect 10
neighbor swp2 interface peer-group underlay
neighbor swp2 advertisement-interval 0
neighbor swp2 timers 3 9
neighbor swp2 timers connect 10
neighbor swp3 interface peer-group underlay
neighbor uplink1 interface remote-as internal
neighbor uplink1 advertisement-interval 0
neighbor uplink1 timers 3 9
neighbor uplink1 timers connect 10
New order:
"router bgp 200 no bgp bestpath as-path multipath-relax"
"router bgp 200 no neighbor underlay advertisement-interval 0"
"router bgp 200 no neighbor underlay timers 3 9"
"router bgp 200 no neighbor underlay timers connect 10"
"router bgp 200 no neighbor uplink1 advertisement-interval 0"
"router bgp 200 no neighbor uplink1 timers 3 9"
"router bgp 200 no neighbor uplink1 timers connect 10"
"router bgp 200 no neighbor underlay remote-as external"
"router bgp 200 no neighbor uplink1 interface remote-as internal"
"router bgp 200 no neighbor underlay peer-group"
"""
# New order:
# "router bgp 200 no bgp bestpath as-path multipath-relax"
# "router bgp 200 no neighbor underlay advertisement-interval 0"
# "router bgp 200 no neighbor underlay timers 3 9"
# "router bgp 200 no neighbor underlay timers connect 10"
# "router bgp 200 no neighbor uplink1 advertisement-interval 0"
# "router bgp 200 no neighbor uplink1 timers 3 9"
# "router bgp 200 no neighbor uplink1 timers connect 10"
# "router bgp 200 no neighbor underlay remote-as external"
# "router bgp 200 no neighbor uplink1 interface remote-as internal"
# "router bgp 200 no neighbor underlay peer-group"
for (ctx_keys, line) in lines_to_del:
if (
@ -860,37 +838,33 @@ def delete_move_lines(lines_to_add, lines_to_del):
and line
and line.startswith("neighbor ")
):
"""
When 'neighbor <peer> remote-as <>' is removed it deletes the peer,
there might be a peer associated config which also needs to be removed
prior to peer.
Append the 'neighbor <peer> remote-as <>' to the lines_to_del.
Example:
# When 'neighbor <peer> remote-as <>' is removed it deletes the peer,
# there might be a peer associated config which also needs to be removed
# prior to peer.
# Append the 'neighbor <peer> remote-as <>' to the lines_to_del.
# Example:
#
# neighbor uplink1 interface remote-as internal
# neighbor uplink1 advertisement-interval 0
# neighbor uplink1 timers 3 9
# neighbor uplink1 timers connect 10
neighbor uplink1 interface remote-as internal
neighbor uplink1 advertisement-interval 0
neighbor uplink1 timers 3 9
neighbor uplink1 timers connect 10
Move to end:
neighbor uplink1 advertisement-interval 0
neighbor uplink1 timers 3 9
neighbor uplink1 timers connect 10
...
neighbor uplink1 interface remote-as internal
"""
# Move to end:
# neighbor uplink1 advertisement-interval 0
# neighbor uplink1 timers 3 9
# neighbor uplink1 timers connect 10
# ...
#
# neighbor uplink1 interface remote-as internal
#
# 'no neighbor peer [interface] remote-as <>'
nb_remoteas = "neighbor (\S+) .*remote-as (\S+)"
re_nb_remoteas = re.search(nb_remoteas, line)
if re_nb_remoteas:
lines_to_del_to_app.append((ctx_keys, line))
"""
{'router bgp 65001': {'PG': [], 'PG1': []},
'router bgp 65001 vrf vrf1': {'PG': [], 'PG1': []}}
"""
# {'router bgp 65001': {'PG': [], 'PG1': []},
# 'router bgp 65001 vrf vrf1': {'PG': [], 'PG1': []}}
if ctx_keys[0] not in del_dict:
del_dict[ctx_keys[0]] = dict()
# find 'no neighbor <pg_name> peer-group'
@ -905,10 +879,8 @@ def delete_move_lines(lines_to_add, lines_to_del):
if found_pg_del_cmd == False:
return (lines_to_add, lines_to_del)
"""
{'router bgp 65001': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']},
'router bgp 65001 vrf vrf1': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}}
"""
# {'router bgp 65001': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']},
# 'router bgp 65001 vrf vrf1': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}}
for (ctx_keys, line) in lines_to_del:
if (
ctx_keys[0].startswith("router bgp")
@ -982,25 +954,22 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
if ctx_keys[0].startswith("router bgp") and line:
if line.startswith("neighbor "):
"""
BGP changed how it displays swpX peers that are part of peer-group. Older
versions of frr would display these on separate lines:
neighbor swp1 interface
neighbor swp1 peer-group FOO
but today we display via a single line
neighbor swp1 interface peer-group FOO
This change confuses frr-reload.py so check to see if we are deleting
neighbor swp1 interface peer-group FOO
and adding
neighbor swp1 interface
neighbor swp1 peer-group FOO
If so then chop the del line and the corresponding add lines
"""
# BGP changed how it displays swpX peers that are part of peer-group. Older
# versions of frr would display these on separate lines:
# neighbor swp1 interface
# neighbor swp1 peer-group FOO
#
# but today we display via a single line
# neighbor swp1 interface peer-group FOO
#
# This change confuses frr-reload.py so check to see if we are deleting
# neighbor swp1 interface peer-group FOO
#
# and adding
# neighbor swp1 interface
# neighbor swp1 peer-group FOO
#
# If so then chop the del line and the corresponding add lines
re_swpx_int_peergroup = re.search(
"neighbor (\S+) interface peer-group (\S+)", line
)
@ -1052,12 +1021,10 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
"""
Changing the bfd timers on neighbors is allowed without doing
a delete/add process. Since doing a "no neighbor blah bfd ..."
will cause the peer to bounce unnecessarily, just skip the delete
and just do the add.
"""
# Changing the bfd timers on neighbors is allowed without doing
# a delete/add process. Since doing a "no neighbor blah bfd
# ..." will cause the peer to bounce unnecessarily, just skip
# the delete and just do the add.
re_nbr_bfd_timers = re.search(
r"neighbor (\S+) bfd (\S+) (\S+) (\S+)", line
)
@ -1081,16 +1048,14 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
if found_add_bfd_nbr:
lines_to_del_to_del.append((ctx_keys, line))
"""
Neighbor changes of route-maps need to be accounted for in that we
do not want to do a `no route-map...` `route-map ....` when changing
a route-map. This is bad mojo as that we will send/receive
data we don't want.
Additionally we need to ensure that if we have different afi/safi
variants that they actually match and if we are going from a very
old style command such that the neighbor command is under the
`router bgp ..` node that we need to handle that appropriately
"""
# Neighbor changes of route-maps need to be accounted for in
# that we do not want to do a `no route-map...` `route-map
# ....` when changing a route-map. This is bad mojo as that we
# will send/receive data we don't want. Additionally we need
# to ensure that if we have different afi/safi variants that
# they actually match and if we are going from a very old style
# command such that the neighbor command is under the `router
# bgp ..` node that we need to handle that appropriately
re_nbr_rm = re.search("neighbor(.*)route-map(.*)(in|out)$", line)
if re_nbr_rm:
adjust_for_bgp_node = 0
@ -1128,29 +1093,27 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
if save_line == dl_line:
lines_to_del_to_del.append((ctx_keys_dl, save_line))
"""
We changed how we display the neighbor interface command. Older
versions of frr would display the following:
neighbor swp1 interface
neighbor swp1 remote-as external
neighbor swp1 capability extended-nexthop
but today we display via a single line
neighbor swp1 interface remote-as external
and capability extended-nexthop is no longer needed because we
automatically enable it when the neighbor is of type interface.
This change confuses frr-reload.py so check to see if we are deleting
neighbor swp1 interface remote-as (external|internal|ASNUM)
and adding
neighbor swp1 interface
neighbor swp1 remote-as (external|internal|ASNUM)
neighbor swp1 capability extended-nexthop
If so then chop the del line and the corresponding add lines
"""
# We changed how we display the neighbor interface command. Older
# versions of frr would display the following:
# neighbor swp1 interface
# neighbor swp1 remote-as external
# neighbor swp1 capability extended-nexthop
#
# but today we display via a single line
# neighbor swp1 interface remote-as external
#
# and capability extended-nexthop is no longer needed because we
# automatically enable it when the neighbor is of type interface.
#
# This change confuses frr-reload.py so check to see if we are deleting
# neighbor swp1 interface remote-as (external|internal|ASNUM)
#
# and adding
# neighbor swp1 interface
# neighbor swp1 remote-as (external|internal|ASNUM)
# neighbor swp1 capability extended-nexthop
#
# If so then chop the del line and the corresponding add lines
re_swpx_int_remoteas = re.search(
"neighbor (\S+) interface remote-as (\S+)", line
)
@ -1186,15 +1149,13 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
"""
We made the 'bgp bestpath as-path multipath-relax' command
automatically assume 'no-as-set' since the lack of this option caused
weird routing problems. When the running config is shown in
releases with this change, the no-as-set keyword is not shown as it
is the default. This causes frr-reload to unnecessarily unapply
this option only to apply it back again, causing unnecessary session
resets.
"""
# We made the 'bgp bestpath as-path multipath-relax' command
# automatically assume 'no-as-set' since the lack of this option
# caused weird routing problems. When the running config is shown
# in releases with this change, the no-as-set keyword is not shown
# as it is the default. This causes frr-reload to unnecessarily
# unapply this option only to apply it back again, causing
# unnecessary session resets.
if "multipath-relax" in line:
re_asrelax_new = re.search(
"^bgp\s+bestpath\s+as-path\s+multipath-relax$", line
@ -1207,25 +1168,21 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, old_asrelax_cmd))
"""
If we are modifying the BGP table-map we need to avoid a del/add and
instead modify the table-map in place via an add. This is needed to
avoid installing all routes in the RIB the second the 'no table-map'
is issued.
"""
# If we are modifying the BGP table-map we need to avoid a del/add
# and instead modify the table-map in place via an add. This is
# needed to avoid installing all routes in the RIB the second the
# 'no table-map' is issued.
if line.startswith("table-map"):
found_table_map = line_exist(lines_to_add, ctx_keys, "table-map", False)
if found_table_map:
lines_to_del_to_del.append((ctx_keys, line))
"""
More old-to-new config handling. ip import-table no longer accepts
distance, but we honor the old syntax. But 'show running' shows only
the new syntax. This causes an unnecessary 'no import-table' followed
by the same old 'ip import-table' which causes perturbations in
announced routes leading to traffic blackholes. Fix this issue.
"""
# More old-to-new config handling. ip import-table no longer accepts
# distance, but we honor the old syntax. But 'show running' shows only
# the new syntax. This causes an unnecessary 'no import-table' followed
# by the same old 'ip import-table' which causes perturbations in
# announced routes leading to traffic blackholes. Fix this issue.
re_importtbl = re.search("^ip\s+import-table\s+(\d+)$", ctx_keys[0])
if re_importtbl:
table_num = re_importtbl.group(1)
@ -1236,17 +1193,16 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
)
lines_to_add_to_del.append((ctx[0], None))
"""
ip/ipv6 prefix-lists and access-lists can be specified without a seq number.
However, the running config always adds 'seq x', where x is a number
incremented by 5 for every element of the prefix/access list.
So, ignore such lines as well. Sample prefix-list and acces-list lines:
ip prefix-list PR-TABLE-2 seq 5 permit 20.8.2.0/24 le 32
ip prefix-list PR-TABLE-2 seq 10 permit 20.8.2.0/24 le 32
ipv6 prefix-list vrfdev6-12 permit 2000:9:2::/64 gt 64
access-list FOO seq 5 permit 2.2.2.2/32
ipv6 access-list BAR seq 5 permit 2:2:2::2/128
"""
# ip/ipv6 prefix-lists and access-lists can be specified without a seq
# number. However, the running config always adds 'seq x', where x is
# a number incremented by 5 for every element of the prefix/access
# list. So, ignore such lines as well. Sample prefix-list and
# acces-list lines:
# ip prefix-list PR-TABLE-2 seq 5 permit 20.8.2.0/24 le 32
# ip prefix-list PR-TABLE-2 seq 10 permit 20.8.2.0/24 le 32
# ipv6 prefix-list vrfdev6-12 permit 2000:9:2::/64 gt 64
# access-list FOO seq 5 permit 2.2.2.2/32
# ipv6 access-list BAR seq 5 permit 2:2:2::2/128
re_acl_pfxlst = re.search(
"^(ip |ipv6 |)(prefix-list|access-list)(\s+\S+\s+)(seq \d+\s+)(permit|deny)(.*)$",
ctx_keys[0],
@ -1265,12 +1221,9 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_del_to_del.append((ctx_keys, None))
lines_to_add_to_del.append(((tmpline,), None))
found = True
"""
If prefix-lists or access-lists are being deleted and
not added (see comment above), add command with 'no' to
lines_to_add and remove from lines_to_del to improve
scaling performance.
"""
# If prefix-lists or access-lists are being deleted and not added
# (see comment above), add command with 'no' to lines_to_add and
# remove from lines_to_del to improve scaling performance.
if found is False:
add_cmd = ("no " + ctx_keys[0],)
lines_to_add.append((add_cmd, None))
@ -1302,16 +1255,12 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add, ctx_keys, route_target_both_line
)
"""
If the running configs has
route-target import 1:1
route-target export 1:1
and the config we are reloading against has
route-target both 1:1
then we can ignore deleting the import/export and ignore adding the 'both'
"""
# If the running configs has
# route-target import 1:1
# route-target export 1:1
# and the config we are reloading against has
# route-target both 1:1
# then we can ignore deleting the import/export and ignore adding the 'both'
if found_route_target_export_line and found_route_target_both_line:
lines_to_del_to_del.append((ctx_keys, route_target_import_line))
lines_to_del_to_del.append((ctx_keys, route_target_export_line))
@ -1333,23 +1282,21 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, line))
else:
"""
We have commands that used to be displayed in the global part
of 'router bgp' that are now displayed under 'address-family ipv4 unicast'
# old way
router bgp 64900
neighbor ISL advertisement-interval 0
vs.
# new way
router bgp 64900
address-family ipv4 unicast
neighbor ISL advertisement-interval 0
Look to see if we are deleting it in one format just to add it back in the other
"""
# We have commands that used to be displayed in the global part
# of 'router bgp' that are now displayed under 'address-family ipv4 unicast'
#
# # old way
# router bgp 64900
# neighbor ISL advertisement-interval 0
#
# vs.
#
# # new way
# router bgp 64900
# address-family ipv4 unicast
# neighbor ISL advertisement-interval 0
#
# Look to see if we are deleting it in one format just to add it back in the other
if (
ctx_keys[0].startswith("router bgp")
and len(ctx_keys) > 1
@ -1382,19 +1329,22 @@ def ignore_unconfigurable_lines(lines_to_add, lines_to_del):
for (ctx_keys, line) in lines_to_del:
if (
ctx_keys[0].startswith("frr version")
or ctx_keys[0].startswith("frr defaults")
or ctx_keys[0].startswith("username")
or ctx_keys[0].startswith("password")
or ctx_keys[0].startswith("line vty")
or
# This is technically "no"able but if we did so frr-reload would
# stop working so do not let the user shoot themselves in the foot
# by removing this.
ctx_keys[0].startswith("service integrated-vtysh-config")
# The integrated-vtysh-config one is technically "no"able but if we did
# so frr-reload would stop working so do not let the user shoot
# themselves in the foot by removing this.
if any(
[
ctx_keys[0].startswith(x)
for x in [
"frr version",
"frr defaults",
"username",
"password",
"line vty",
"service integrated-vtysh-config",
]
]
):
log.info('"%s" cannot be removed' % (ctx_keys[-1],))
lines_to_del_to_del.append((ctx_keys, line))