summaryrefslogtreecommitdiff
path: root/src/migration-scripts/quagga/6-to-7
blob: 095baac030ceeb3177c2921a415957fb6b65bc26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Copyright 2021-2024 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library.  If not, see <http://www.gnu.org/licenses/>.

# - T3037, BGP address-family ipv6-unicast capability dynamic does not exist in
#   FRR, there is only a base, per neighbor dynamic capability, migrate config

from vyos.configtree import ConfigTree
from vyos.template import is_ipv4
from vyos.template import is_ipv6

base = ['protocols', 'bgp']

def migrate(config: ConfigTree) -> None:
    if not config.exists(base):
        # Nothing to do
        return

    # Check if BGP is actually configured and obtain the ASN
    asn_list = config.list_nodes(base)
    if asn_list:
        # There's always just one BGP node, if any
        bgp_base = base + [asn_list[0]]

        for neighbor_type in ['neighbor', 'peer-group']:
            if not config.exists(bgp_base + [neighbor_type]):
                continue
            for neighbor in config.list_nodes(bgp_base + [neighbor_type]):
                # T2844 - add IPv4 AFI disable-send-community support
                send_comm_path = bgp_base + [neighbor_type, neighbor, 'disable-send-community']
                if config.exists(send_comm_path):
                    new_base = bgp_base + [neighbor_type, neighbor, 'address-family', 'ipv4-unicast']
                    config.set(new_base)
                    config.copy(send_comm_path, new_base + ['disable-send-community'])
                    config.delete(send_comm_path)

                cap_dynamic = False
                peer_group = None
                for afi in ['ipv4-unicast', 'ipv6-unicast']:
                    afi_path = bgp_base + [neighbor_type, neighbor, 'address-family', afi]
                    # Exit loop early if AFI does not exist
                    if not config.exists(afi_path):
                        continue

                    cap_path = afi_path + ['capability', 'dynamic']
                    if config.exists(cap_path):
                        cap_dynamic = True
                        config.delete(cap_path)

                        # We have now successfully migrated the address-family
                        # specific dynamic capability to the neighbor/peer-group
                        # level. If this has been the only option under the
                        # address-family nodes, we can clean them up by checking if
                        # no other nodes are left under that tree and if so, delete
                        # the parent.
                        #
                        # We walk from the most inner node to the most outer one.
                        cleanup = -1
                        while len(config.list_nodes(cap_path[:cleanup])) == 0:
                            config.delete(cap_path[:cleanup])
                            cleanup -= 1

                    peer_group_path = afi_path + ['peer-group']
                    if config.exists(peer_group_path):
                        if ((is_ipv4(neighbor) and afi == 'ipv4-unicast') or
                            (is_ipv6(neighbor) and afi == 'ipv6-unicast')):
                            peer_group = config.return_value(peer_group_path)

                        config.delete(peer_group_path)

                        # We have now successfully migrated the address-family
                        # specific peer-group to the neighbor level. If this has
                        # been the only option under the address-family nodes, we
                        # can clean them up by checking if no other nodes are left
                        # under that tree and if so, delete the parent.
                        #
                        # We walk from the most inner node to the most outer one.
                        cleanup = -1
                        while len(config.list_nodes(peer_group_path[:cleanup])) == 0:
                            config.delete(peer_group_path[:cleanup])
                            cleanup -= 1

                if cap_dynamic:
                    config.set(bgp_base + [neighbor_type, neighbor, 'capability', 'dynamic'])
                if peer_group:
                    config.set(bgp_base + [neighbor_type, neighbor, 'peer-group'], value=peer_group)