]>
Commit | Line | Data |
---|---|---|
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 | 21 | from collections import OrderedDict |
2ad3d000 | 22 | from json import dumps as json_dumps |
bca79837 | 23 | from re import search as re_search |
2ad3d000 | 24 | import ipaddr |
7659b8d4 | 25 | import pytest |
2ad3d000 AP |
26 | |
27 | # Import topogen and topotest helpers | |
28 | from lib.topolog import logger | |
29 | ||
30 | # Required to instantiate the topology builder class. | |
7659b8d4 AP |
31 | from lib.common_config import ( |
32 | number_to_row, number_to_column, | |
33 | load_config_to_router, | |
e4663527 | 34 | create_interfaces_cfg, |
00db2a89 AP |
35 | create_static_routes, |
36 | create_prefix_lists, | |
e6db2bb1 | 37 | create_route_maps, |
9920237e | 38 | create_bgp_community_lists |
7659b8d4 | 39 | ) |
2ad3d000 | 40 | |
7fa2079a | 41 | from lib.bgp import create_router_bgp |
2ad3d000 | 42 | |
bca79837 AP |
43 | ROUTER_LIST = [] |
44 | ||
45 | ||
2ad3d000 AP |
46 | def build_topo_from_json(tgen, topo): |
47 | """ | |
48 | Reads configuration from JSON file. Adds routers, creates interface | |
49 | names dynamically and link routers as defined in JSON to create | |
50 | topology. Assigns IPs dynamically to all interfaces of each router. | |
51 | ||
52 | * `tgen`: Topogen object | |
53 | * `topo`: json file data | |
54 | """ | |
55 | ||
bca79837 AP |
56 | ROUTER_LIST = sorted(topo['routers'].keys(), |
57 | key=lambda x: int(re_search('\d+', x).group(0))) | |
58 | ||
59 | listRouters = ROUTER_LIST[:] | |
60 | for routerN in ROUTER_LIST: | |
61 | logger.info('Topo: Add router {}'.format(routerN)) | |
62 | tgen.add_router(routerN) | |
63 | listRouters.append(routerN) | |
2ad3d000 | 64 | |
2ad3d000 AP |
65 | if 'ipv4base' in topo: |
66 | ipv4Next = ipaddr.IPv4Address(topo['link_ip_start']['ipv4']) | |
67 | ipv4Step = 2 ** (32 - topo['link_ip_start']['v4mask']) | |
68 | if topo['link_ip_start']['v4mask'] < 32: | |
69 | ipv4Next += 1 | |
70 | if 'ipv6base' in topo: | |
71 | ipv6Next = ipaddr.IPv6Address(topo['link_ip_start']['ipv6']) | |
72 | ipv6Step = 2 ** (128 - topo['link_ip_start']['v6mask']) | |
73 | if topo['link_ip_start']['v6mask'] < 127: | |
74 | ipv6Next += 1 | |
75 | for router in listRouters: | |
76 | topo['routers'][router]['nextIfname'] = 0 | |
77 | ||
78 | while listRouters != []: | |
79 | curRouter = listRouters.pop(0) | |
80 | # Physical Interfaces | |
81 | if 'links' in topo['routers'][curRouter]: | |
82 | def link_sort(x): | |
83 | if x == 'lo': | |
84 | return 0 | |
85 | elif 'link' in x: | |
86 | return int(x.split('-link')[1]) | |
87 | else: | |
bca79837 | 88 | return int(re_search('\d+', x).group(0)) |
2ad3d000 AP |
89 | for destRouterLink, data in sorted(topo['routers'][curRouter]['links']. \ |
90 | iteritems(), | |
91 | key=lambda x: link_sort(x[0])): | |
92 | currRouter_lo_json = \ | |
93 | topo['routers'][curRouter]['links'][destRouterLink] | |
94 | # Loopback interfaces | |
95 | if 'type' in data and data['type'] == 'loopback': | |
96 | if 'ipv4' in currRouter_lo_json and \ | |
97 | currRouter_lo_json['ipv4'] == 'auto': | |
98 | currRouter_lo_json['ipv4'] = '{}{}.{}/{}'. \ | |
99 | format(topo['lo_prefix']['ipv4'], number_to_row(curRouter), \ | |
100 | number_to_column(curRouter), topo['lo_prefix']['v4mask']) | |
101 | if 'ipv6' in currRouter_lo_json and \ | |
102 | currRouter_lo_json['ipv6'] == 'auto': | |
103 | currRouter_lo_json['ipv6'] = '{}{}:{}/{}'. \ | |
104 | format(topo['lo_prefix']['ipv6'], number_to_row(curRouter), \ | |
105 | number_to_column(curRouter), topo['lo_prefix']['v6mask']) | |
106 | ||
107 | if "-" in destRouterLink: | |
108 | # Spliting and storing destRouterLink data in tempList | |
109 | tempList = destRouterLink.split("-") | |
110 | ||
111 | # destRouter | |
112 | destRouter = tempList.pop(0) | |
113 | ||
114 | # Current Router Link | |
115 | tempList.insert(0, curRouter) | |
116 | curRouterLink = "-".join(tempList) | |
117 | else: | |
118 | destRouter = destRouterLink | |
119 | curRouterLink = curRouter | |
120 | ||
121 | if destRouter in listRouters: | |
122 | currRouter_link_json = \ | |
123 | topo['routers'][curRouter]['links'][destRouterLink] | |
124 | destRouter_link_json = \ | |
125 | topo['routers'][destRouter]['links'][curRouterLink] | |
126 | ||
127 | # Assigning name to interfaces | |
128 | currRouter_link_json['interface'] = \ | |
129 | '{}-{}-eth{}'.format(curRouter, destRouter, topo['routers'] \ | |
130 | [curRouter]['nextIfname']) | |
131 | destRouter_link_json['interface'] = \ | |
132 | '{}-{}-eth{}'.format(destRouter, curRouter, topo['routers'] \ | |
133 | [destRouter]['nextIfname']) | |
134 | ||
135 | topo['routers'][curRouter]['nextIfname'] += 1 | |
136 | topo['routers'][destRouter]['nextIfname'] += 1 | |
137 | ||
138 | # Linking routers to each other as defined in JSON file | |
139 | tgen.gears[curRouter].add_link(tgen.gears[destRouter], | |
140 | topo['routers'][curRouter]['links'][destRouterLink] \ | |
141 | ['interface'], topo['routers'][destRouter]['links'] \ | |
142 | [curRouterLink]['interface']) | |
143 | ||
144 | # IPv4 | |
145 | if 'ipv4' in currRouter_link_json: | |
146 | if currRouter_link_json['ipv4'] == 'auto': | |
147 | currRouter_link_json['ipv4'] = \ | |
148 | '{}/{}'.format(ipv4Next, topo['link_ip_start'][ \ | |
149 | 'v4mask']) | |
150 | destRouter_link_json['ipv4'] = \ | |
151 | '{}/{}'.format(ipv4Next + 1, topo['link_ip_start'][ \ | |
152 | 'v4mask']) | |
153 | ipv4Next += ipv4Step | |
154 | # IPv6 | |
155 | if 'ipv6' in currRouter_link_json: | |
156 | if currRouter_link_json['ipv6'] == 'auto': | |
157 | currRouter_link_json['ipv6'] = \ | |
158 | '{}/{}'.format(ipv6Next, topo['link_ip_start'][ \ | |
159 | 'v6mask']) | |
160 | destRouter_link_json['ipv6'] = \ | |
161 | '{}/{}'.format(ipv6Next + 1, topo['link_ip_start'][ \ | |
162 | 'v6mask']) | |
163 | ipv6Next = ipaddr.IPv6Address(int(ipv6Next) + ipv6Step) | |
164 | ||
165 | logger.debug("Generated link data for router: %s\n%s", curRouter, | |
166 | json_dumps(topo["routers"][curRouter]["links"], | |
7fa2079a AP |
167 | indent=4, sort_keys=True)) |
168 | ||
7659b8d4 AP |
169 | |
170 | def build_config_from_json(tgen, topo, save_bkup=True): | |
171 | """ | |
172 | Reads initial configuraiton from JSON for each router, builds | |
173 | configuration and loads its to router. | |
174 | ||
175 | * `tgen`: Topogen object | |
176 | * `topo`: json file data | |
177 | """ | |
178 | ||
179 | func_dict = OrderedDict([ | |
180 | ("links", create_interfaces_cfg), | |
e4663527 | 181 | ("static_routes", create_static_routes), |
00db2a89 | 182 | ("prefix_lists", create_prefix_lists), |
9920237e | 183 | ("bgp_community_list", create_bgp_community_lists), |
e6db2bb1 | 184 | ("route_maps", create_route_maps), |
7fa2079a | 185 | ("bgp", create_router_bgp) |
7659b8d4 AP |
186 | ]) |
187 | ||
188 | data = topo["routers"] | |
189 | for func_type in func_dict.keys(): | |
bca79837 AP |
190 | logger.info('Checking for {} configuration in input data'.format( |
191 | func_type)) | |
7659b8d4 AP |
192 | |
193 | func_dict.get(func_type)(tgen, data, build=True) | |
194 | ||
195 | for router in sorted(topo['routers'].keys()): | |
bca79837 | 196 | logger.debug('Configuring router {}...'.format(router)) |
7659b8d4 AP |
197 | |
198 | result = load_config_to_router(tgen, router, save_bkup) | |
199 | if not result: | |
200 | logger.info("Failed while configuring {}".format(router)) | |
201 | pytest.exit(1) | |
202 |