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