b5612a110199be57be38eec815f3c49f074543e6
[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(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=False)
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 not not yet connected
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 # check connectivity by using ping
167 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
168 # stop Mininet network
169 self.stopNet()
170
171 def testSDNChainingMultiService(self):
172 """
173 Create a two data centers and interconnect them with additional
174 switches between them.
175 Uses Ryu SDN controller.
176 Setup 2 services and setup isolated paths between them
177 Delete only the first service, and check that other one still works
178 """
179 # create network
180 self.createNet(
181 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
182 autolinkswitches=True,
183 controller=RemoteController,
184 enable_learning=False)
185 # setup links
186 self.net.addLink(self.dc[0], self.s[0])
187 self.net.addLink(self.s[2], self.dc[1])
188 # start Mininet network
189 self.startNet()
190
191 ## First Service
192 # add compute resources
193 vnf1 = self.dc[0].startCompute("vnf1", network=[{'id': 'intf1', 'ip': '10.0.10.1/24'}])
194 vnf2 = self.dc[1].startCompute("vnf2", network=[{'id': 'intf2', 'ip': '10.0.10.2/24'}])
195 # setup links
196 self.net.setChain('vnf1', 'vnf2', 'intf1', 'intf2', bidirectional=True, cmd='add-flow', cookie=1)
197 # check connectivity by using ping
198 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
199
200 ## Second Service
201 # add compute resources
202 vnf11 = self.dc[0].startCompute("vnf11", network=[{'id': 'intf1', 'ip': '10.0.20.1/24'}])
203 vnf22 = self.dc[1].startCompute("vnf22", network=[{'id': 'intf2', 'ip': '10.0.20.2/24'}])
204
205 # check number of running nodes
206 self.assertTrue(len(self.getContainernetContainers()) == 4)
207 self.assertTrue(len(self.net.hosts) == 4)
208 self.assertTrue(len(self.net.switches) == 5)
209
210 # setup links
211 self.net.setChain('vnf11', 'vnf22', 'intf1', 'intf2', bidirectional=True, cmd='add-flow', cookie=2)
212 # check connectivity by using ping
213 self.assertTrue(self.net.ping([vnf11, vnf22]) <= 0.0)
214 # check first service cannot ping second service
215 self.assertTrue(self.net.ping([vnf1, vnf22]) > 0.0)
216 self.assertTrue(self.net.ping([vnf2, vnf11]) > 0.0)
217
218 # delete the first service chain
219 self.net.setChain('vnf1', 'vnf2', 'intf1', 'intf2', bidirectional=True, cmd='del-flows', cookie=1)
220 # check connectivity of first service is down
221 self.assertTrue(self.net.ping([vnf1, vnf2]) > 0.0)
222 #time.sleep(100)
223 # check connectivity of second service is still up
224 self.assertTrue(self.net.ping([vnf11, vnf22]) <= 0.0)
225
226 # stop Mininet network
227 self.stopNet()
228
229 #@unittest.skip("disabled compute tests for development")
230 class testEmulatorCompute( SimpleTestTopology ):
231 """
232 Tests to check the emulator's API to add and remove
233 compute resources at runtime.
234 """
235
236 def testAddSingleComputeSingleDC(self):
237 """
238 Adds a single compute instance to
239 a single DC and checks its connectivity with a
240 manually added host.
241 """
242 # create network
243 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
244 # setup links
245 self.net.addLink(self.dc[0], self.h[0])
246 # start Mininet network
247 self.startNet()
248 # add compute resources
249 vnf1 = self.dc[0].startCompute("vnf1")
250 # check number of running nodes
251 self.assertTrue(len(self.getContainernetContainers()) == 1)
252 self.assertTrue(len(self.net.hosts) == 2)
253 self.assertTrue(len(self.net.switches) == 1)
254 # check compute list result
255 self.assertTrue(len(self.dc[0].listCompute()) == 1)
256 self.assertTrue(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
257 self.assertTrue(self.dc[0].listCompute()[0].name == "vnf1")
258 # check connectivity by using ping
259 self.assertTrue(self.net.ping([self.h[0], vnf1]) <= 0.0)
260 # stop Mininet network
261 self.stopNet()
262
263 def testRemoveSingleComputeSingleDC(self):
264 """
265 Test stop method for compute instances.
266 Check that the instance is really removed.
267 """
268 # create network
269 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
270 # setup links
271 self.net.addLink(self.dc[0], self.h[0])
272 # start Mininet network
273 self.startNet()
274 # add compute resources
275 vnf1 = self.dc[0].startCompute("vnf1")
276 # check number of running nodes
277 self.assertTrue(len(self.getContainernetContainers()) == 1)
278 self.assertTrue(len(self.net.hosts) == 2)
279 self.assertTrue(len(self.net.switches) == 1)
280 # check compute list result
281 self.assertTrue(len(self.dc[0].listCompute()) == 1)
282 # check connectivity by using ping
283 self.assertTrue(self.net.ping([self.h[0], vnf1]) <= 0.0)
284 # remove compute resources
285 self.dc[0].stopCompute("vnf1")
286 # check number of running nodes
287 self.assertTrue(len(self.getContainernetContainers()) == 0)
288 self.assertTrue(len(self.net.hosts) == 1)
289 self.assertTrue(len(self.net.switches) == 1)
290 # check compute list result
291 self.assertTrue(len(self.dc[0].listCompute()) == 0)
292 # stop Mininet network
293 self.stopNet()
294
295 def testGetStatusSingleComputeSingleDC(self):
296 """
297 Check if the getStatus functionality of EmulatorCompute
298 objects works well.
299 """
300 # create network
301 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
302 # setup links
303 self.net.addLink(self.dc[0], self.h[0])
304 # start Mininet network
305 self.startNet()
306 # add compute resources
307 vnf1 = self.dc[0].startCompute("vnf1")
308 # check number of running nodes
309 self.assertTrue(len(self.getContainernetContainers()) == 1)
310 self.assertTrue(len(self.net.hosts) == 2)
311 self.assertTrue(len(self.net.switches) == 1)
312 # check compute list result
313 self.assertTrue(len(self.dc[0].listCompute()) == 1)
314 self.assertTrue(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
315 self.assertTrue(self.dc[0].listCompute()[0].name == "vnf1")
316 # check connectivity by using ping
317 self.assertTrue(self.net.ping([self.h[0], vnf1]) <= 0.0)
318 # check get status
319 s = self.dc[0].containers.get("vnf1").getStatus()
320 self.assertTrue(s["name"] == "vnf1")
321 self.assertTrue(s["state"]["Running"])
322 # stop Mininet network
323 self.stopNet()
324
325 def testConnectivityMultiDC(self):
326 """
327 Test if compute instances started in different data centers
328 are able to talk to each other.
329 """
330 # create network
331 self.createNet(
332 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
333 autolinkswitches=True)
334 # setup links
335 self.net.addLink(self.dc[0], self.s[0])
336 self.net.addLink(self.dc[1], self.s[2])
337 # start Mininet network
338 self.startNet()
339 # add compute resources
340 vnf1 = self.dc[0].startCompute("vnf1")
341 vnf2 = self.dc[1].startCompute("vnf2")
342 # check number of running nodes
343 self.assertTrue(len(self.getContainernetContainers()) == 2)
344 self.assertTrue(len(self.net.hosts) == 2)
345 self.assertTrue(len(self.net.switches) == 5)
346 # check compute list result
347 self.assertTrue(len(self.dc[0].listCompute()) == 1)
348 self.assertTrue(len(self.dc[1].listCompute()) == 1)
349 # check connectivity by using ping
350 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
351 # stop Mininet network
352 self.stopNet()
353
354 def testInterleavedAddRemoveMultiDC(self):
355 """
356 Test multiple, interleaved add and remove operations and ensure
357 that always all expected compute instances are reachable.
358 """
359 # create network
360 self.createNet(
361 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
362 autolinkswitches=True)
363 # setup links
364 self.net.addLink(self.dc[0], self.s[0])
365 self.net.addLink(self.dc[1], self.s[2])
366 # start Mininet network
367 self.startNet()
368 # add compute resources
369 vnf1 = self.dc[0].startCompute("vnf1")
370 vnf2 = self.dc[1].startCompute("vnf2")
371 # check number of running nodes
372 self.assertTrue(len(self.getContainernetContainers()) == 2)
373 self.assertTrue(len(self.net.hosts) == 2)
374 self.assertTrue(len(self.net.switches) == 5)
375 # check compute list result
376 self.assertTrue(len(self.dc[0].listCompute()) == 1)
377 self.assertTrue(len(self.dc[1].listCompute()) == 1)
378 # check connectivity by using ping
379 self.assertTrue(self.net.ping([vnf1, vnf2]) <= 0.0)
380 # remove compute resources
381 self.dc[0].stopCompute("vnf1")
382 # check number of running nodes
383 self.assertTrue(len(self.getContainernetContainers()) == 1)
384 self.assertTrue(len(self.net.hosts) == 1)
385 self.assertTrue(len(self.net.switches) == 5)
386 # check compute list result
387 self.assertTrue(len(self.dc[0].listCompute()) == 0)
388 self.assertTrue(len(self.dc[1].listCompute()) == 1)
389 # add compute resources
390 vnf3 = self.dc[0].startCompute("vnf3")
391 vnf4 = self.dc[0].startCompute("vnf4")
392 # check compute list result
393 self.assertTrue(len(self.dc[0].listCompute()) == 2)
394 self.assertTrue(len(self.dc[1].listCompute()) == 1)
395 self.assertTrue(self.net.ping([vnf3, vnf2]) <= 0.0)
396 self.assertTrue(self.net.ping([vnf4, vnf2]) <= 0.0)
397 # remove compute resources
398 self.dc[0].stopCompute("vnf3")
399 self.dc[0].stopCompute("vnf4")
400 self.dc[1].stopCompute("vnf2")
401 # check compute list result
402 self.assertTrue(len(self.dc[0].listCompute()) == 0)
403 self.assertTrue(len(self.dc[1].listCompute()) == 0)
404 # stop Mininet network
405 self.stopNet()
406
407 if __name__ == '__main__':
408 unittest.main()