]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/lib/topojson.py
Merge pull request #7089 from pguibert6WIND/netns-refactor
[mirror_frr.git] / tests / topotests / lib / topojson.py
CommitLineData
2ad3d000
AP
1#
2# Modified work Copyright (c) 2019 by VMware, Inc. ("VMware")
3# Original work Copyright (c) 2018 by Network Device Education
4# Foundation, Inc. ("NetDEF")
5#
6# Permission to use, copy, modify, and/or distribute this software
7# for any purpose with or without fee is hereby granted, provided
8# that the above copyright notice and this permission notice appear
9# in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
15# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
16# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
17# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
18# OF THIS SOFTWARE.
19#
20
7659b8d4 21from collections import OrderedDict
2ad3d000 22from json import dumps as json_dumps
bca79837 23from re import search as re_search
8b547a6d 24import ipaddress
7659b8d4 25import pytest
2ad3d000
AP
26
27# Import topogen and topotest helpers
28from lib.topolog import logger
29
30# Required to instantiate the topology builder class.
7659b8d4 31from lib.common_config import (
787e7624 32 number_to_row,
33 number_to_column,
7659b8d4 34 load_config_to_router,
e4663527 35 create_interfaces_cfg,
00db2a89
AP
36 create_static_routes,
37 create_prefix_lists,
e6db2bb1 38 create_route_maps,
787e7624 39 create_bgp_community_lists,
f8d572e8 40 create_vrf_cfg,
7659b8d4 41)
2ad3d000 42
7fa2079a 43from lib.bgp import create_router_bgp
2ad3d000 44
bca79837
AP
45ROUTER_LIST = []
46
47
2ad3d000
AP
48def build_topo_from_json(tgen, topo):
49 """
50 Reads configuration from JSON file. Adds routers, creates interface
51 names dynamically and link routers as defined in JSON to create
52 topology. Assigns IPs dynamically to all interfaces of each router.
2ad3d000
AP
53 * `tgen`: Topogen object
54 * `topo`: json file data
55 """
56
787e7624 57 ROUTER_LIST = sorted(
58 topo["routers"].keys(), key=lambda x: int(re_search("\d+", x).group(0))
59 )
bca79837
AP
60
61 listRouters = ROUTER_LIST[:]
62 for routerN in ROUTER_LIST:
787e7624 63 logger.info("Topo: Add router {}".format(routerN))
bca79837
AP
64 tgen.add_router(routerN)
65 listRouters.append(routerN)
2ad3d000 66
787e7624 67 if "ipv4base" in topo:
8b547a6d 68 ipv4Next = ipaddress.IPv4Address(topo["link_ip_start"]["ipv4"])
787e7624 69 ipv4Step = 2 ** (32 - topo["link_ip_start"]["v4mask"])
70 if topo["link_ip_start"]["v4mask"] < 32:
2ad3d000 71 ipv4Next += 1
787e7624 72 if "ipv6base" in topo:
8b547a6d 73 ipv6Next = ipaddress.IPv6Address(topo["link_ip_start"]["ipv6"])
787e7624 74 ipv6Step = 2 ** (128 - topo["link_ip_start"]["v6mask"])
75 if topo["link_ip_start"]["v6mask"] < 127:
2ad3d000
AP
76 ipv6Next += 1
77 for router in listRouters:
787e7624 78 topo["routers"][router]["nextIfname"] = 0
2ad3d000
AP
79
80 while listRouters != []:
81 curRouter = listRouters.pop(0)
82 # Physical Interfaces
787e7624 83 if "links" in topo["routers"][curRouter]:
84
2ad3d000 85 def link_sort(x):
787e7624 86 if x == "lo":
2ad3d000 87 return 0
787e7624 88 elif "link" in x:
89 return int(x.split("-link")[1])
2ad3d000 90 else:
787e7624 91 return int(re_search("\d+", x).group(0))
92
93 for destRouterLink, data in sorted(
94 topo["routers"][curRouter]["links"].iteritems(),
95 key=lambda x: link_sort(x[0]),
96 ):
97 currRouter_lo_json = topo["routers"][curRouter]["links"][destRouterLink]
2ad3d000 98 # Loopback interfaces
787e7624 99 if "type" in data and data["type"] == "loopback":
100 if (
101 "ipv4" in currRouter_lo_json
102 and currRouter_lo_json["ipv4"] == "auto"
103 ):
104 currRouter_lo_json["ipv4"] = "{}{}.{}/{}".format(
105 topo["lo_prefix"]["ipv4"],
106 number_to_row(curRouter),
107 number_to_column(curRouter),
108 topo["lo_prefix"]["v4mask"],
109 )
110 if (
111 "ipv6" in currRouter_lo_json
112 and currRouter_lo_json["ipv6"] == "auto"
113 ):
114 currRouter_lo_json["ipv6"] = "{}{}:{}/{}".format(
115 topo["lo_prefix"]["ipv6"],
116 number_to_row(curRouter),
117 number_to_column(curRouter),
118 topo["lo_prefix"]["v6mask"],
119 )
2ad3d000
AP
120
121 if "-" in destRouterLink:
122 # Spliting and storing destRouterLink data in tempList
123 tempList = destRouterLink.split("-")
124
125 # destRouter
126 destRouter = tempList.pop(0)
127
128 # Current Router Link
129 tempList.insert(0, curRouter)
130 curRouterLink = "-".join(tempList)
131 else:
132 destRouter = destRouterLink
133 curRouterLink = curRouter
134
135 if destRouter in listRouters:
787e7624 136 currRouter_link_json = topo["routers"][curRouter]["links"][
137 destRouterLink
138 ]
139 destRouter_link_json = topo["routers"][destRouter]["links"][
140 curRouterLink
141 ]
2ad3d000
AP
142
143 # Assigning name to interfaces
787e7624 144 currRouter_link_json["interface"] = "{}-{}-eth{}".format(
145 curRouter, destRouter, topo["routers"][curRouter]["nextIfname"]
146 )
147 destRouter_link_json["interface"] = "{}-{}-eth{}".format(
148 destRouter, curRouter, topo["routers"][destRouter]["nextIfname"]
149 )
2ad3d000 150
787e7624 151 topo["routers"][curRouter]["nextIfname"] += 1
152 topo["routers"][destRouter]["nextIfname"] += 1
2ad3d000
AP
153
154 # Linking routers to each other as defined in JSON file
787e7624 155 tgen.gears[curRouter].add_link(
156 tgen.gears[destRouter],
157 topo["routers"][curRouter]["links"][destRouterLink][
158 "interface"
159 ],
160 topo["routers"][destRouter]["links"][curRouterLink][
161 "interface"
162 ],
163 )
2ad3d000
AP
164
165 # IPv4
787e7624 166 if "ipv4" in currRouter_link_json:
167 if currRouter_link_json["ipv4"] == "auto":
168 currRouter_link_json["ipv4"] = "{}/{}".format(
169 ipv4Next, topo["link_ip_start"]["v4mask"]
170 )
171 destRouter_link_json["ipv4"] = "{}/{}".format(
172 ipv4Next + 1, topo["link_ip_start"]["v4mask"]
173 )
2ad3d000
AP
174 ipv4Next += ipv4Step
175 # IPv6
787e7624 176 if "ipv6" in currRouter_link_json:
177 if currRouter_link_json["ipv6"] == "auto":
178 currRouter_link_json["ipv6"] = "{}/{}".format(
179 ipv6Next, topo["link_ip_start"]["v6mask"]
180 )
181 destRouter_link_json["ipv6"] = "{}/{}".format(
182 ipv6Next + 1, topo["link_ip_start"]["v6mask"]
183 )
8b547a6d 184 ipv6Next = ipaddress.IPv6Address(int(ipv6Next) + ipv6Step)
2ad3d000 185
787e7624 186 logger.debug(
187 "Generated link data for router: %s\n%s",
188 curRouter,
189 json_dumps(
190 topo["routers"][curRouter]["links"], indent=4, sort_keys=True
191 ),
192 )
7fa2079a 193
7659b8d4
AP
194
195def build_config_from_json(tgen, topo, save_bkup=True):
196 """
197 Reads initial configuraiton from JSON for each router, builds
198 configuration and loads its to router.
199
200 * `tgen`: Topogen object
201 * `topo`: json file data
202 """
203
787e7624 204 func_dict = OrderedDict(
205 [
f8d572e8 206 ("vrfs", create_vrf_cfg),
787e7624 207 ("links", create_interfaces_cfg),
208 ("static_routes", create_static_routes),
209 ("prefix_lists", create_prefix_lists),
210 ("bgp_community_list", create_bgp_community_lists),
211 ("route_maps", create_route_maps),
212 ("bgp", create_router_bgp),
213 ]
214 )
7659b8d4
AP
215
216 data = topo["routers"]
217 for func_type in func_dict.keys():
787e7624 218 logger.info("Checking for {} configuration in input data".format(func_type))
7659b8d4
AP
219
220 func_dict.get(func_type)(tgen, data, build=True)
221
787e7624 222 for router in sorted(topo["routers"].keys()):
223 logger.debug("Configuring router {}...".format(router))
7659b8d4
AP
224
225 result = load_config_to_router(tgen, router, save_bkup)
226 if not result:
227 logger.info("Failed while configuring {}".format(router))
228 pytest.exit(1)