4 # Copyright 2016 RIFT.IO Inc
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
21 gi
.require_version('RwYang', '1.0')
22 from gi
.repository
import IetfL2TopologyYang
as l2Tl
23 from gi
.repository
import RwTopologyYang
as RwTl
24 from gi
.repository
import RwYang
25 from xml
.etree
import ElementTree
as etree
29 from create_stackedl2topology
import MyL2Network
30 from create_stackedl2topology
import MyL2Topology
31 from create_stackedProvNettopology
import MyProvNetwork
32 from create_stackedProvNettopology
import MyProvTopology
34 class MyNwNotFound(Exception):
37 class MyNodeNotFound(Exception):
40 class MyTpNotFound(Exception):
43 class MyVMNetwork(object):
44 def __init__(self
, nwtop
, l2top
, provtop
, log
):
47 self
.vmnet1
= nwtop
.network
.add()
48 self
.vmnet1
.network_id
= "VmNetwork-1"
52 self
.provtop
= provtop
54 # L2 Network type augmentation
55 self
.vmnet1
.network_types
.l2_network
= self
.vmnet1
.network_types
.l2_network
.new()
56 # L2 Network augmentation
57 self
.vmnet1
.l2_network_attributes
.name
= "Rift LAB SFC-Demo VM Network"
58 ul_net
= self
.vmnet1
.supporting_network
.add()
60 ul_net
.network_ref
= l2top
.find_nw_id("L2HostNetwork-1")
61 self
.l2netid
= ul_net
.network_ref
64 ul_net
= self
.vmnet1
.supporting_network
.add()
66 ul_net
.network_ref
= provtop
.find_nw_id("ProviderNetwork-1")
67 self
.provnetid
= ul_net
.network_ref
71 def get_nw_id(self
, nw_name
):
72 for nw
in self
.nwtop
.network
:
73 if (nw
.network_id
== nw_name
):
76 def get_node(self
, node_name
):
77 _node_id
= "urn:Rift:Lab:" + node_name
78 for node
in self
.vmnet1
.node
:
79 if (node
.node_id
== _node_id
):
82 def get_tp(self
, node
, tp_name
):
83 _tp_id
= node
.node_id
+ "_" + tp_name
84 for tp
in node
.termination_point
:
85 if (tp
.tp_id
== _tp_id
):
88 def get_link(self
, link_name
):
90 if (link
.l2_link_attributes
.name
== link_name
):
93 def create_node(self
, node_name
, description
, mgmt_ip_addr
=None, sup_node_list
=None):
94 logging
.debug("Creating node %s", node_name
)
95 node
= self
.vmnet1
.node
.add()
96 node
.node_id
= "urn:Rift:Lab:" + node_name
97 # L2 Node augmentation
98 node
.l2_node_attributes
.name
= node_name
99 node
.l2_node_attributes
.description
= description
100 if (mgmt_ip_addr
is not None):
101 node
.l2_node_attributes
.management_address
.append(mgmt_ip_addr
)
102 if (sup_node_list
is not None):
103 for sup_node
in sup_node_list
:
104 logging
.debug(" Adding support node %s", sup_node
[0].node_id
)
105 ul_node
= node
.supporting_node
.add()
106 # Second element is hardcoded as nw ref
107 if (sup_node
[1] is not None):
108 ul_node
.network_ref
= sup_node
[1]
110 ul_node
.network_ref
= self
.l2netid
111 ul_node
.node_ref
= sup_node
[0].node_id
114 def create_tp(self
, node
, cfg_tp
, sup_node
= None, sup_tp
= None, nw_ref
= None):
115 logging
.debug(" Creating termination point %s %s", node
.l2_node_attributes
.name
, cfg_tp
)
116 tp
= node
.termination_point
.add()
117 tp
.tp_id
= ("{}:{}").format(node
.node_id
, cfg_tp
)
119 tp
.l2_termination_point_attributes
.description
= cfg_tp
120 tp
.l2_termination_point_attributes
.maximum_frame_size
= 1500
121 tp
.l2_termination_point_attributes
.mac_address
= "00:5e:8a:ab:cc:" + str(self
.next_mac
)
122 self
.next_mac
= self
.next_mac
+ 1
123 tp
.l2_termination_point_attributes
.eth_encapsulation
= "l2t:ethernet"
124 if ((sup_tp
is not None) and (sup_node
is not None)):
125 logging
.debug(" Adding support terminaton point %s", sup_tp
.tp_id
)
126 ul_tp
= tp
.supporting_termination_point
.add()
127 if (nw_ref
is not None):
128 ul_tp
.network_ref
= nw_ref
130 ul_tp
.network_ref
= self
.l2netid
131 ul_tp
.node_ref
= sup_node
.node_id
132 ul_tp
.tp_ref
= sup_tp
.tp_id
135 def create_bidir_link(self
, node1
, tp1
, node2
, tp2
, link_name1
, link_name2
):
136 logging
.debug("Creating links %s %s", link_name1
, link_name2
)
137 lnk1
= self
.vmnet1
.link
.add()
138 lnk1
.link_id
= "urn:Rift:Lab:Ethernet:{}{}_{}{}".format(node1
.l2_node_attributes
.name
, tp1
.l2_termination_point_attributes
.description
, node2
.l2_node_attributes
.name
, tp2
.l2_termination_point_attributes
.description
)
139 lnk1
.source
.source_node
= node1
.node_id
140 lnk1
.source
.source_tp
= tp1
.tp_id
141 lnk1
.destination
.dest_node
= node2
.node_id
142 lnk1
.destination
.dest_tp
= tp2
.tp_id
143 # L2 link augmentation
144 lnk1
.l2_link_attributes
.name
= link_name1
145 #lnk1.l2_link_attributes.rate = 1000000000.00
147 lnk2
= self
.vmnet1
.link
.add()
148 lnk2
.link_id
= "urn:Rift:Lab:Ethernet:{}{}_{}{}".format(node2
.l2_node_attributes
.name
, tp2
.l2_termination_point_attributes
.description
, node1
.l2_node_attributes
.name
, tp1
.l2_termination_point_attributes
.description
)
149 lnk2
.source
.source_node
= node2
.node_id
150 lnk2
.source
.source_tp
= tp2
.tp_id
151 lnk2
.destination
.dest_node
= node1
.node_id
152 lnk2
.destination
.dest_tp
= tp1
.tp_id
153 # L2 link augmentation
154 lnk2
.l2_link_attributes
.name
= link_name2
155 #lnk2.l2_link_attributes.rate = 1000000000.00
158 class MyVMTopology(MyVMNetwork
):
159 def __init__(self
, nwtop
, l2top
, provtop
, log
):
160 super(MyVMTopology
, self
).__init
__(nwtop
, l2top
, provtop
, log
)
162 def find_nw_id(self
, nw_name
):
163 return self
.get_nw_id(nw_name
)
165 def find_node(self
, node_name
):
166 return self
.get_node(node_name
)
168 def find_tp(self
, node
, tp_name
):
169 return self
.get_tp(node
, tp_name
)
172 def find_link(self
, link_name
):
173 return self
.get_link(link_name
)
175 def setup_nodes(self
):
176 logging
.debug("Setting up nodes")
178 self
.g118_node
= self
.l2top
.find_node("Grunt118")
179 if (self
.g118_node
is None):
180 raise MyNodeNotFound()
181 self
.g44_node
= self
.l2top
.find_node("Grunt44")
182 if (self
.g44_node
is None):
183 raise MyNodeNotFound()
184 self
.g120_node
= self
.l2top
.find_node("Grunt120")
185 if (self
.g120_node
is None):
186 raise MyNodeNotFound()
188 self
.g44_br_int_node
= self
.provtop
.find_node("G44_Br_Int")
189 if (self
.g44_br_int_node
is None):
190 raise MyNodeNotFound()
192 self
.pseudo_vm
= self
.create_node("Pseudo_VM","Pseudo VM to manage eth0 LAN")
193 sup_node_list
= [[self
.g118_node
, self
.l2netid
], [self
.g44_br_int_node
, self
.provnetid
]]
194 self
.tg_vm
= self
.create_node("Trafgen_VM","Trafgen VM on Grunt118", mgmt_ip_addr
="10.0.118.3", sup_node_list
= sup_node_list
)
195 sup_node_list
= [[self
.g44_node
, self
.l2netid
], [self
.g44_br_int_node
, self
.provnetid
]]
196 self
.lb_vm
= self
.create_node("LB_VM","LB VM on Grunt44", mgmt_ip_addr
="10.0.118.35", sup_node_list
= sup_node_list
)
197 sup_node_list
= [[self
.g120_node
, self
.l2netid
], [self
.g44_br_int_node
, self
.provnetid
]]
198 self
.ts_vm
= self
.create_node("Trafsink_VM","Trafsink VM on Grunt120", mgmt_ip_addr
="10.0.118.4", sup_node_list
= sup_node_list
)
201 logging
.debug("Setting up termination points")
203 self
.g118_e2
= self
.l2top
.find_tp(self
.g118_node
, "eth2")
204 if (self
.g118_e2
is None):
206 self
.g44_e2
= self
.l2top
.find_tp(self
.g44_node
, "eth2")
207 if (self
.g44_e2
is None):
210 self
.g44_br_int_vhu2
= self
.provtop
.find_tp(self
.g44_br_int_node
, "vhu2")
211 if (self
.g44_br_int_vhu2
is None):
213 self
.g44_br_int_vhu3
= self
.provtop
.find_tp(self
.g44_br_int_node
, "vhu3")
214 if (self
.g44_br_int_vhu3
is None):
217 self
.pvm_eth1
= self
.create_tp(self
.pseudo_vm
, "eth1")
218 self
.pvm_eth2
= self
.create_tp(self
.pseudo_vm
, "eth2")
219 self
.pvm_eth3
= self
.create_tp(self
.pseudo_vm
, "eth3")
221 self
.tg_vm_eth0
= self
.create_tp(self
.tg_vm
, "eth0")
222 self
.tg_vm_trafgen11
= self
.create_tp(self
.tg_vm
, "trafgen11", sup_node
=self
.g118_node
, sup_tp
=self
.g118_e2
)
224 self
.lb_vm_eth0
= self
.create_tp(self
.lb_vm
, "eth0")
225 self
.lb_vm_lb21
= self
.create_tp(self
.lb_vm
, "load_balancer21", sup_node
=self
.g44_br_int_node
, sup_tp
=self
.g44_br_int_vhu2
, nw_ref
=self
.provnetid
)
226 self
.lb_vm_lb22
= self
.create_tp(self
.lb_vm
, "load_balancer22", sup_node
=self
.g44_br_int_node
, sup_tp
=self
.g44_br_int_vhu3
, nw_ref
=self
.provnetid
)
228 self
.ts_vm_eth0
= self
.create_tp(self
.ts_vm
, "eth0")
229 self
.ts_vm_trafsink31
= self
.create_tp(self
.ts_vm
, "trafsink31", sup_node
=self
.g44_node
, sup_tp
=self
.g44_e2
)
232 def setup_links(self
):
233 # Add links to vmnet1 network
234 # These links are unidirectional and point-to-point
235 logging
.debug("Setting up links")
236 # Bidir Links for OVS bridges
237 self
.create_bidir_link(self
.tg_vm
, self
.tg_vm_trafgen11
, self
.lb_vm
, self
.lb_vm_lb21
, "Link_tg_t11_lb_lb21", "Link_lb_lb21_tg_t11")
238 self
.create_bidir_link(self
.ts_vm
, self
.ts_vm_trafsink31
, self
.lb_vm
, self
.lb_vm_lb22
, "Link_ts_t31_lb_lb22", "Link_lb_lb22_tg_t31")
240 self
.create_bidir_link(self
.pseudo_vm
, self
.pvm_eth1
, self
.tg_vm
, self
.tg_vm_eth0
, "Link_pvm_e1_tgv_e0", "Link_tgv_e0_pvm_e1")
241 self
.create_bidir_link(self
.pseudo_vm
, self
.pvm_eth2
, self
.lb_vm
, self
.lb_vm_eth0
, "Link_pvm_e2_lbv_e0", "Link_lbv_e0_pvm_e2")
242 self
.create_bidir_link(self
.pseudo_vm
, self
.pvm_eth3
, self
.ts_vm
, self
.ts_vm_eth0
, "Link_pvm_e3_tsv_e0", "Link_tsv_e0_pvm_e3")
249 def adjust_xml_file(infile
, outfile
, begin_marker
, end_marker
):
252 max_interesting_line_toread
= 1
254 with
open(infile
) as inf
:
255 with
open(outfile
, 'w') as outf
:
257 if begin_marker
in line
:
260 if end_marker
in line
:
261 assert in_block
is True
262 print("End of gathering line...", line
)
263 buffer.append(line
) # gather lines
264 interesting_line
= max_interesting_line_toread
268 print("Interesting line printing ...", line
)
270 interesting_line
-= 1
271 if interesting_line
== 0: # output gathered lines
274 buffer = [] # empty buffer
279 print("Gathering line...", line
)
280 buffer.append(line
) # gather lines
285 if __name__
== "__main__":
286 model
= RwYang
.Model
.create_libyang()
287 model
.load_schema_ypbc(RwTl
.get_schema())
289 logger
= logging
.getLogger('VM Network Topology')
290 logger
.setLevel(logging
.DEBUG
)
291 logging
.basicConfig(level
=logging
.DEBUG
)
293 logger
.info('Creating an instance of VM Network Topology')
295 nwtop
= RwTl
.YangData_IetfNetwork()
298 l2top
= MyL2Topology(nwtop
, logger
)
301 # Setup Provider network topology
302 provtop
= MyProvTopology(nwtop
, l2top
, logger
)
305 # Setup VM network topology
306 vmtop
= MyVMTopology(nwtop
, l2top
, provtop
, logger
)
309 print ("Converting to XML")
310 # Convert l2nw network to XML
311 xml_str
= nwtop
.to_xml_v2(model
)
312 tree
= etree
.XML(xml_str
)
313 xml_file
= "/tmp/stacked_vmtop.xml"
314 xml_formatted_file
= "/tmp/stacked_vmtop2.xml"
315 with
open(xml_file
, "w") as f
:
317 status
= subprocess
.call("xmllint --format " + xml_file
+ " > " + xml_formatted_file
, shell
=True)
319 status
= subprocess
.call("sed -i '/xml version/d' " + xml_formatted_file
, shell
=True)
320 status
= subprocess
.call("sed -i '/root xmlns/d' " + xml_formatted_file
, shell
=True)
321 status
= subprocess
.call("sed -i '/\/root/d' " + xml_formatted_file
, shell
=True)
323 print ("Converting to JSON ")
324 # Convert set of topologies to JSON
325 json_str
= nwtop
.to_json(model
)
326 with
open("/tmp/stacked_vmtop.json", "w") as f
:
328 status
= subprocess
.call("python -m json.tool /tmp/stacked_vmtop.json > /tmp/stacked_vmtop2.json", shell
=True)
329 json_formatted_file
= "/tmp/stacked_vmtop2.json"
330 status
= subprocess
.call("sed -i -e 's/\"l2t:ethernet\"/\"ethernet\"/g' " + json_formatted_file
, shell
=True)
331 status
= subprocess
.call("sed -i -e 's/\"l2t:vlan\"/\"vlan\"/g' " + json_formatted_file
, shell
=True)