94db55fa08e1bccdd26054440a1b3e3743df8cdb
[osm/vim-emu.git] / src / emuvim / test / unittests / test_emulator.py
1 """
2 Copyright (c) 2015 SONATA-NFV
3 ALL RIGHTS RESERVED.
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 Neither the name of the SONATA-NFV [, ANY ADDITIONAL AFFILIATION]
18 nor the names of its contributors may be used to endorse or promote
19 products derived from this software without specific prior written
20 permission.
21
22 This work has been performed in the framework of the SONATA project,
23 funded by the European Commission under Grant number 671517 through
24 the Horizon 2020 and 5G-PPP programmes. The authors would like to
25 acknowledge the contributions of their colleagues of the SONATA
26 partner consortium (www.sonata-nfv.eu).
27 """
28 """
29 Test suite to automatically test emulator functionalities.
30 Directly interacts with the emulator through the Mininet-like
31 Python API.
32
33 Does not test API endpoints. This is done in separated test suites.
34 """
35
36 import time
37 import unittest
38 from emuvim.dcemulator.node import EmulatorCompute
39 from emuvim.test.base import SimpleTestTopology
40 from mininet.node import RemoteController
41
42
43 #@unittest.skip("disabled topology tests for development")
44 class testEmulatorTopology( SimpleTestTopology ):
45 """
46 Tests to check the topology API of the emulator.
47 """
48
49 def testSingleDatacenter(self):
50 """
51 Create a single data center and add check if its switch is up
52 by using manually added hosts. Tests especially the
53 data center specific addLink method.
54 """
55 # create network
56 self.createNet(nswitches=0, ndatacenter=1, nhosts=2, ndockers=0)
57 # setup links
58 self.net.addLink(self.dc[0], self.h[0])
59 self.net.addLink(self.h[1], self.dc[0])
60 # start Mininet network
61 self.startNet()
62 # check number of running nodes
63 self.assertTrue(len(self.getContainernetContainers()) == 0)
64 self.assertTrue(len(self.net.hosts) == 2)
65 self.assertTrue(len(self.net.switches) == 1)
66 # check connectivity by using ping
67 self.assertTrue(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
68 # stop Mininet network
69 self.stopNet()
70
71 #@unittest.skip("disabled to test if CI fails because this is the first test.")
72 def testMultipleDatacenterDirect(self):
73 """
74 Create a two data centers and interconnect them.
75 """
76 # create network
77 self.createNet(nswitches=0, ndatacenter=2, nhosts=2, ndockers=0)
78 # setup links
79 self.net.addLink(self.dc[0], self.h[0])
80 self.net.addLink(self.h[1], self.dc[1])
81 self.net.addLink(self.dc[0], self.dc[1])
82 # start Mininet network
83 self.startNet()
84 # check number of running nodes
85 self.assertTrue(len(self.getContainernetContainers()) == 0)
86 self.assertTrue(len(self.net.hosts) == 2)
87 self.assertTrue(len(self.net.switches) == 2)
88 # check connectivity by using ping
89 self.assertTrue(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
90 # stop Mininet network
91 self.stopNet()
92
93 def testMultipleDatacenterWithIntermediateSwitches(self):
94 """
95 Create a two data centers and interconnect them with additional
96 switches between them.
97 """
98 # create network
99 self.createNet(
100 nswitches=3, ndatacenter=2, nhosts=2, ndockers=0,
101 autolinkswitches=True)
102 # setup links
103 self.net.addLink(self.dc[0], self.h[0])
104 self.net.addLink(self.h[1], self.dc[1])
105 self.net.addLink(self.dc[0], self.s[0])
106 self.net.addLink(self.s[2], self.dc[1])
107 # start Mininet network
108 self.startNet()
109 # check number of running nodes
110 self.assertTrue(len(self.getContainernetContainers()) == 0)
111 self.assertTrue(len(self.net.hosts) == 2)
112 self.assertTrue(len(self.net.switches) == 5)
113 # check connectivity by using ping
114 self.assertTrue(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
115 # stop Mininet network
116 self.stopNet()
117
118 class testEmulatorNetworking( SimpleTestTopology ):
119
120 def testSDNChainingSingleService_withLearning(self):
121 """
122 Create a two data centers and interconnect them with additional
123 switches between them.
124 Uses Ryu SDN controller.
125 Connect the Docker hosts to different datacenters and setup the links between.
126 """
127 # create network
128 self.createNet(
129 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
130 autolinkswitches=True,
131 controller=RemoteController,
132 enable_learning=True)
133 # setup links
134 self.net.addLink(self.dc[0], self.s[0])
135 self.net.addLink(self.s[2], self.dc[1])
136 # start Mininet network
137 self.startNet()
138
139 # add compute resources
140 vnf1 = self.dc[0].startCompute("vnf1", network=[{'id':'intf1', 'ip':'10.0.10.1/24'}])
141 vnf2 = self.dc[1].startCompute("vnf2", network=[{'id':'intf2', 'ip':'10.0.10.2/24'}])
142 # check number of running nodes
143 self.assertTrue(len(self.getContainernetContainers()) == 2)
144 self.assertTrue(len(self.net.hosts) == 2)
145 self.assertTrue(len(self.net.switches) == 5)
146 # check status
147 # check get status
148 s1 = self.dc[0].containers.get("vnf1").getStatus()
149 print s1
150 self.assertTrue(s1["name"] == "vnf1")
151 self.assertTrue(s1["state"]["Running"])
152 self.assertTrue(s1["network"][0]['intf_name'] == 'intf1')
153 self.assertTrue(s1["network"][0]['ip'] == '10.0.10.1/24')
154
155 s2 = self.dc[1].containers.get("vnf2").getStatus()
156 print s2
157 self.assertTrue(s2["name"] == "vnf2")
158 self.assertTrue(s2["state"]["Running"])
159 self.assertTrue(s2["network"][0]['intf_name'] == 'intf2')
160 self.assertTrue(s2["network"][0]['ip'] == '10.0.10.2/24')
161
162 # should be connected because learning = True
163 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
164 # setup links
165 self.net.setChain('vnf1', 'vnf2', 'intf1', 'intf2', bidirectional=True, cmd='add-flow')
166 # should still be connected
167 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
168 # stop Mininet network
169 self.stopNet()
170
171 def testSDNChainingSingleService(self):
172 """
173 Create a two data centers and interconnect them with additional
174 switches between them.
175 Uses Ryu SDN controller.
176 Connect the Docker hosts to different datacenters and setup the links between.
177 """
178 # create network
179 self.createNet(
180 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
181 autolinkswitches=True,
182 controller=RemoteController,
183 enable_learning=False)
184 # setup links
185 self.net.addLink(self.dc[0], self.s[0])
186 self.net.addLink(self.s[2], self.dc[1])
187 # start Mininet network
188 self.startNet()
189
190 # add compute resources
191 vnf1 = self.dc[0].startCompute("vnf1", network=[{'id':'intf1', 'ip':'10.0.10.1/24'}])
192 vnf2 = self.dc[1].startCompute("vnf2", network=[{'id':'intf2', 'ip':'10.0.10.2/24'}])
193 # check number of running nodes
194 self.assertTrue(len(self.getContainernetContainers()) == 2)
195 self.assertTrue(len(self.net.hosts) == 2)
196 self.assertTrue(len(self.net.switches) == 5)
197 # check status
198 # check get status
199 s1 = self.dc[0].containers.get("vnf1").getStatus()
200 print s1
201 self.assertTrue(s1["name"] == "vnf1")
202 self.assertTrue(s1["state"]["Running"])
203 self.assertTrue(s1["network"][0]['intf_name'] == 'intf1')
204 self.assertTrue(s1["network"][0]['ip'] == '10.0.10.1/24')
205
206 s2 = self.dc[1].containers.get("vnf2").getStatus()
207 print s2
208 self.assertTrue(s2["name"] == "vnf2")
209 self.assertTrue(s2["state"]["Running"])
210 self.assertTrue(s2["network"][0]['intf_name'] == 'intf2')
211 self.assertTrue(s2["network"][0]['ip'] == '10.0.10.2/24')
212
213 # should be not not yet connected
214 self.assertTrue(self.net.ping([vnf1, vnf2]) > 0.0)
215 # setup links
216 self.net.setChain('vnf1', 'vnf2', 'intf1', 'intf2', bidirectional=True, cmd='add-flow')
217 # check connectivity by using ping
218 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
219 # stop Mininet network
220 self.stopNet()
221
222 def testSDNChainingMultiService(self):
223 """
224 Create a two data centers and interconnect them with additional
225 switches between them.
226 Uses Ryu SDN controller.
227 Setup 2 services and setup isolated paths between them
228 Delete only the first service, and check that other one still works
229 """
230 # create network
231 self.createNet(
232 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
233 autolinkswitches=True,
234 controller=RemoteController,
235 enable_learning=False)
236 # setup links
237 self.net.addLink(self.dc[0], self.s[0])
238 self.net.addLink(self.s[2], self.dc[1])
239 # start Mininet network
240 self.startNet()
241
242 ## First Service
243 # add compute resources
244 vnf1 = self.dc[0].startCompute("vnf1", network=[{'id': 'intf1', 'ip': '10.0.10.1/24'}])
245 vnf2 = self.dc[1].startCompute("vnf2", network=[{'id': 'intf2', 'ip': '10.0.10.2/24'}])
246 # setup links
247 self.net.setChain('vnf1', 'vnf2', 'intf1', 'intf2', bidirectional=True, cmd='add-flow', cookie=1)
248 # check connectivity by using ping
249 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
250
251 ## Second Service
252 # add compute resources
253 vnf11 = self.dc[0].startCompute("vnf11", network=[{'id': 'intf1', 'ip': '10.0.20.1/24'}])
254 vnf22 = self.dc[1].startCompute("vnf22", network=[{'id': 'intf2', 'ip': '10.0.20.2/24'}])
255
256 # check number of running nodes
257 self.assertTrue(len(self.getContainernetContainers()) == 4)
258 self.assertTrue(len(self.net.hosts) == 4)
259 self.assertTrue(len(self.net.switches) == 5)
260
261 # setup links
262 self.net.setChain('vnf11', 'vnf22', 'intf1', 'intf2', bidirectional=True, cmd='add-flow', cookie=2)
263 # check connectivity by using ping
264 self.assertTrue(self.net.ping([vnf11, vnf22]) <= 0.0)
265 # check first service cannot ping second service
266 self.assertTrue(self.net.ping([vnf1, vnf22]) > 0.0)
267 self.assertTrue(self.net.ping([vnf2, vnf11]) > 0.0)
268
269 # delete the first service chain
270 self.net.setChain('vnf1', 'vnf2', 'intf1', 'intf2', bidirectional=True, cmd='del-flows', cookie=1)
271 # check connectivity of first service is down
272 self.assertTrue(self.net.ping([vnf1, vnf2]) > 0.0)
273 #time.sleep(100)
274 # check connectivity of second service is still up
275 self.assertTrue(self.net.ping([vnf11, vnf22]) <= 0.0)
276
277 # stop Mininet network
278 self.stopNet()
279
280 #@unittest.skip("disabled compute tests for development")
281 class testEmulatorCompute( SimpleTestTopology ):
282 """
283 Tests to check the emulator's API to add and remove
284 compute resources at runtime.
285 """
286
287 def testAddSingleComputeSingleDC(self):
288 """
289 Adds a single compute instance to
290 a single DC and checks its connectivity with a
291 manually added host.
292 """
293 # create network
294 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
295 # setup links
296 self.net.addLink(self.dc[0], self.h[0])
297 # start Mininet network
298 self.startNet()
299 # add compute resources
300 vnf1 = self.dc[0].startCompute("vnf1")
301 # check number of running nodes
302 self.assertTrue(len(self.getContainernetContainers()) == 1)
303 self.assertTrue(len(self.net.hosts) == 2)
304 self.assertTrue(len(self.net.switches) == 1)
305 # check compute list result
306 self.assertTrue(len(self.dc[0].listCompute()) == 1)
307 self.assertTrue(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
308 self.assertTrue(self.dc[0].listCompute()[0].name == "vnf1")
309 # check connectivity by using ping
310 self.assertTrue(self.net.ping([self.h[0], vnf1]) <= 0.0)
311 # stop Mininet network
312 self.stopNet()
313
314 def testRemoveSingleComputeSingleDC(self):
315 """
316 Test stop method for compute instances.
317 Check that the instance is really removed.
318 """
319 # create network
320 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
321 # setup links
322 self.net.addLink(self.dc[0], self.h[0])
323 # start Mininet network
324 self.startNet()
325 # add compute resources
326 vnf1 = self.dc[0].startCompute("vnf1")
327 # check number of running nodes
328 self.assertTrue(len(self.getContainernetContainers()) == 1)
329 self.assertTrue(len(self.net.hosts) == 2)
330 self.assertTrue(len(self.net.switches) == 1)
331 # check compute list result
332 self.assertTrue(len(self.dc[0].listCompute()) == 1)
333 # check connectivity by using ping
334 self.assertTrue(self.net.ping([self.h[0], vnf1]) <= 0.0)
335 # remove compute resources
336 self.dc[0].stopCompute("vnf1")
337 # check number of running nodes
338 self.assertTrue(len(self.getContainernetContainers()) == 0)
339 self.assertTrue(len(self.net.hosts) == 1)
340 self.assertTrue(len(self.net.switches) == 1)
341 # check compute list result
342 self.assertTrue(len(self.dc[0].listCompute()) == 0)
343 # stop Mininet network
344 self.stopNet()
345
346 def testGetStatusSingleComputeSingleDC(self):
347 """
348 Check if the getStatus functionality of EmulatorCompute
349 objects works well.
350 """
351 # create network
352 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
353 # setup links
354 self.net.addLink(self.dc[0], self.h[0])
355 # start Mininet network
356 self.startNet()
357 # add compute resources
358 vnf1 = self.dc[0].startCompute("vnf1")
359 # check number of running nodes
360 self.assertTrue(len(self.getContainernetContainers()) == 1)
361 self.assertTrue(len(self.net.hosts) == 2)
362 self.assertTrue(len(self.net.switches) == 1)
363 # check compute list result
364 self.assertTrue(len(self.dc[0].listCompute()) == 1)
365 self.assertTrue(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
366 self.assertTrue(self.dc[0].listCompute()[0].name == "vnf1")
367 # check connectivity by using ping
368 self.assertTrue(self.net.ping([self.h[0], vnf1]) <= 0.0)
369 # check get status
370 s = self.dc[0].containers.get("vnf1").getStatus()
371 self.assertTrue(s["name"] == "vnf1")
372 self.assertTrue(s["state"]["Running"])
373 # stop Mininet network
374 self.stopNet()
375
376 def testConnectivityMultiDC(self):
377 """
378 Test if compute instances started in different data centers
379 are able to talk to each other.
380 """
381 # create network
382 self.createNet(
383 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
384 autolinkswitches=True)
385 # setup links
386 self.net.addLink(self.dc[0], self.s[0])
387 self.net.addLink(self.dc[1], self.s[2])
388 # start Mininet network
389 self.startNet()
390 # add compute resources
391 vnf1 = self.dc[0].startCompute("vnf1")
392 vnf2 = self.dc[1].startCompute("vnf2")
393 # check number of running nodes
394 self.assertTrue(len(self.getContainernetContainers()) == 2)
395 self.assertTrue(len(self.net.hosts) == 2)
396 self.assertTrue(len(self.net.switches) == 5)
397 # check compute list result
398 self.assertTrue(len(self.dc[0].listCompute()) == 1)
399 self.assertTrue(len(self.dc[1].listCompute()) == 1)
400 # check connectivity by using ping
401 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
402 # stop Mininet network
403 self.stopNet()
404
405 def testInterleavedAddRemoveMultiDC(self):
406 """
407 Test multiple, interleaved add and remove operations and ensure
408 that always all expected compute instances are reachable.
409 """
410 # create network
411 self.createNet(
412 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
413 autolinkswitches=True)
414 # setup links
415 self.net.addLink(self.dc[0], self.s[0])
416 self.net.addLink(self.dc[1], self.s[2])
417 # start Mininet network
418 self.startNet()
419 # add compute resources
420 vnf1 = self.dc[0].startCompute("vnf1")
421 vnf2 = self.dc[1].startCompute("vnf2")
422 # check number of running nodes
423 self.assertTrue(len(self.getContainernetContainers()) == 2)
424 self.assertTrue(len(self.net.hosts) == 2)
425 self.assertTrue(len(self.net.switches) == 5)
426 # check compute list result
427 self.assertTrue(len(self.dc[0].listCompute()) == 1)
428 self.assertTrue(len(self.dc[1].listCompute()) == 1)
429 # check connectivity by using ping
430 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
431 # remove compute resources
432 self.dc[0].stopCompute("vnf1")
433 # check number of running nodes
434 self.assertTrue(len(self.getContainernetContainers()) == 1)
435 self.assertTrue(len(self.net.hosts) == 1)
436 self.assertTrue(len(self.net.switches) == 5)
437 # check compute list result
438 self.assertTrue(len(self.dc[0].listCompute()) == 0)
439 self.assertTrue(len(self.dc[1].listCompute()) == 1)
440 # add compute resources
441 vnf3 = self.dc[0].startCompute("vnf3")
442 vnf4 = self.dc[0].startCompute("vnf4")
443 # check compute list result
444 self.assertTrue(len(self.dc[0].listCompute()) == 2)
445 self.assertTrue(len(self.dc[1].listCompute()) == 1)
446 self.assertTrue(self.net.ping([vnf3, vnf2]) <= 0.0)
447 self.assertTrue(self.net.ping([vnf4, vnf2]) <= 0.0)
448 # remove compute resources
449 self.dc[0].stopCompute("vnf3")
450 self.dc[0].stopCompute("vnf4")
451 self.dc[1].stopCompute("vnf2")
452 # check compute list result
453 self.assertTrue(len(self.dc[0].listCompute()) == 0)
454 self.assertTrue(len(self.dc[1].listCompute()) == 0)
455 # stop Mininet network
456 self.stopNet()
457
458 if __name__ == '__main__':
459 unittest.main()