Using absolute import path
[osm/vim-emu.git] / src / emuvim / test / test_emulator.py
1 """
2 Test suite to automatically test emulator functionalities.
3 Directly interacts with the emulator through the Mininet-like
4 Python API.
5
6 Does not test API endpoints. This is done in separated test suites.
7 """
8
9 import unittest
10 import os
11 import time
12 import subprocess
13 import docker
14 from emuvim.dcemulator.net import DCNetwork
15 from emuvim.dcemulator.node import EmulatorCompute
16 from mininet.node import Host, Controller, OVSSwitch, Docker
17 from mininet.link import TCLink
18 from mininet.topo import SingleSwitchTopo, LinearTopo
19 from mininet.log import setLogLevel
20 from mininet.util import quietRun
21 from mininet.clean import cleanup
22
23
24 class simpleTestTopology( unittest.TestCase ):
25 """
26 Helper class to do basic test setups.
27 s1 -- s2 -- s3 -- ... -- sN
28 """
29
30 def __init__(self, *args, **kwargs):
31 self.net = None
32 self.s = [] # list of switches
33 self.h = [] # list of hosts
34 self.d = [] # list of docker containers
35 self.dc = [] # list of data centers
36 self.docker_cli = None
37 super(simpleTestTopology, self).__init__(*args, **kwargs)
38
39 def createNet(
40 self,
41 nswitches=0, ndatacenter=0, nhosts=0, ndockers=0,
42 autolinkswitches=False):
43 """
44 Creates a Mininet instance and automatically adds some
45 nodes to it.
46 """
47 self.net = net = DCNetwork()
48
49 # add some switches
50 for i in range(0, nswitches):
51 self.s.append(self.net.addSwitch('s%d' % i))
52 # if specified, chain all switches
53 if autolinkswitches:
54 for i in range(0, len(self.s) - 1):
55 self.net.addLink(self.s[i], self.s[i + 1])
56 # add some data centers
57 for i in range(0, ndatacenter):
58 self.dc.append(
59 self.net.addDatacenter(
60 'datacenter%d' % i,
61 metadata={"unittest_dc": i}))
62 # add some hosts
63 for i in range(0, nhosts):
64 self.h.append(self.net.addHost('h%d' % i))
65 # add some dockers
66 for i in range(0, ndockers):
67 self.d.append(self.net.addDocker('d%d' % i, dimage="ubuntu"))
68
69 def startNet(self):
70 self.net.start()
71
72 def stopNet(self):
73 self.net.stop()
74
75 def getDockerCli(self):
76 """
77 Helper to interact with local docker instance.
78 """
79 if self.docker_cli is None:
80 self.docker_cli = docker.Client(
81 base_url='unix://var/run/docker.sock')
82 return self.docker_cli
83
84 def getDockernetContainers(self):
85 """
86 List the containers managed by dockernet
87 """
88 return self.getDockerCli().containers(filters={"label": "com.dockernet"})
89
90 @staticmethod
91 def setUp():
92 pass
93
94 @staticmethod
95 def tearDown():
96 cleanup()
97 # make sure that all pending docker containers are killed
98 with open(os.devnull, 'w') as devnull:
99 subprocess.call(
100 "sudo docker rm -f $(sudo docker ps --filter 'label=com.dockernet' -a -q)",
101 stdout=devnull,
102 stderr=devnull,
103 shell=True)
104
105
106 #@unittest.skip("disabled topology tests for development")
107 class testEmulatorTopology( simpleTestTopology ):
108 """
109 Tests to check the topology API of the emulator.
110 """
111
112 def testSingleDatacenter(self):
113 """
114 Create a single data center and add check if its switch is up
115 by using manually added hosts. Tests especially the
116 data center specific addLink method.
117 """
118 # create network
119 self.createNet(nswitches=0, ndatacenter=1, nhosts=2, ndockers=0)
120 # setup links
121 self.net.addLink(self.dc[0], self.h[0])
122 self.net.addLink(self.h[1], self.dc[0])
123 # start Mininet network
124 self.startNet()
125 # check number of running nodes
126 assert(len(self.getDockernetContainers()) == 0)
127 assert(len(self.net.hosts) == 2)
128 assert(len(self.net.switches) == 1)
129 # check connectivity by using ping
130 assert(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
131 # stop Mininet network
132 self.stopNet()
133
134 def testMultipleDatacenterDirect(self):
135 """
136 Create a two data centers and interconnect them.
137 """
138 # create network
139 self.createNet(nswitches=0, ndatacenter=2, nhosts=2, ndockers=0)
140 # setup links
141 self.net.addLink(self.dc[0], self.h[0])
142 self.net.addLink(self.h[1], self.dc[1])
143 self.net.addLink(self.dc[0], self.dc[1])
144 # start Mininet network
145 self.startNet()
146 # check number of running nodes
147 assert(len(self.getDockernetContainers()) == 0)
148 assert(len(self.net.hosts) == 2)
149 assert(len(self.net.switches) == 2)
150 # check connectivity by using ping
151 assert(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
152 # stop Mininet network
153 self.stopNet()
154
155 def testMultipleDatacenterWithIntermediateSwitches(self):
156 """
157 Create a two data centers and interconnect them with additional
158 switches between them.
159 """
160 # create network
161 self.createNet(
162 nswitches=3, ndatacenter=2, nhosts=2, ndockers=0,
163 autolinkswitches=True)
164 # setup links
165 self.net.addLink(self.dc[0], self.h[0])
166 self.net.addLink(self.h[1], self.dc[1])
167 self.net.addLink(self.dc[0], self.s[0])
168 self.net.addLink(self.s[2], self.dc[1])
169 # start Mininet network
170 self.startNet()
171 # check number of running nodes
172 assert(len(self.getDockernetContainers()) == 0)
173 assert(len(self.net.hosts) == 2)
174 assert(len(self.net.switches) == 5)
175 # check connectivity by using ping
176 assert(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
177 # stop Mininet network
178 self.stopNet()
179
180
181 #@unittest.skip("disabled compute tests for development")
182 class testEmulatorCompute( simpleTestTopology ):
183 """
184 Tests to check the emulator's API to add and remove
185 compute resources at runtime.
186 """
187
188 def testAddSingleComputeSingleDC(self):
189 """
190 Adds a single compute instance to
191 a single DC and checks its connectivity with a
192 manually added host.
193 """
194 # create network
195 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
196 # setup links
197 self.net.addLink(self.dc[0], self.h[0])
198 # start Mininet network
199 self.startNet()
200 # add compute resources
201 vnf1 = self.dc[0].startCompute("vnf1")
202 # check number of running nodes
203 assert(len(self.getDockernetContainers()) == 1)
204 assert(len(self.net.hosts) == 2)
205 assert(len(self.net.switches) == 1)
206 # check compute list result
207 assert(len(self.dc[0].listCompute()) == 1)
208 assert(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
209 assert(self.dc[0].listCompute()[0].name == "vnf1")
210 # check connectivity by using ping
211 assert(self.net.ping([self.h[0], vnf1]) <= 0.0)
212 # stop Mininet network
213 self.stopNet()
214
215 def testRemoveSingleComputeSingleDC(self):
216 """
217 Test stop method for compute instances.
218 Check that the instance is really removed.
219 """
220 # create network
221 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
222 # setup links
223 self.net.addLink(self.dc[0], self.h[0])
224 # start Mininet network
225 self.startNet()
226 # add compute resources
227 vnf1 = self.dc[0].startCompute("vnf1")
228 # check number of running nodes
229 assert(len(self.getDockernetContainers()) == 1)
230 assert(len(self.net.hosts) == 2)
231 assert(len(self.net.switches) == 1)
232 # check compute list result
233 assert(len(self.dc[0].listCompute()) == 1)
234 # check connectivity by using ping
235 assert(self.net.ping([self.h[0], vnf1]) <= 0.0)
236 # remove compute resources
237 self.dc[0].stopCompute("vnf1")
238 # check number of running nodes
239 assert(len(self.getDockernetContainers()) == 0)
240 assert(len(self.net.hosts) == 1)
241 assert(len(self.net.switches) == 1)
242 # check compute list result
243 assert(len(self.dc[0].listCompute()) == 0)
244 # stop Mininet network
245 self.stopNet()
246
247 def testGetStatusSingleComputeSingleDC(self):
248 """
249 Check if the getStatus functionality of EmulatorCompute
250 objects works well.
251 """
252 # create network
253 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
254 # setup links
255 self.net.addLink(self.dc[0], self.h[0])
256 # start Mininet network
257 self.startNet()
258 # add compute resources
259 vnf1 = self.dc[0].startCompute("vnf1")
260 # check number of running nodes
261 assert(len(self.getDockernetContainers()) == 1)
262 assert(len(self.net.hosts) == 2)
263 assert(len(self.net.switches) == 1)
264 # check compute list result
265 assert(len(self.dc[0].listCompute()) == 1)
266 assert(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
267 assert(self.dc[0].listCompute()[0].name == "vnf1")
268 # check connectivity by using ping
269 assert(self.net.ping([self.h[0], vnf1]) <= 0.0)
270 # check get status
271 s = self.dc[0].containers.get("vnf1").getStatus()
272 assert(s["name"] == "vnf1")
273 assert(s["state"]["Running"])
274 # stop Mininet network
275 self.stopNet()
276
277 def testConnectivityMultiDC(self):
278 """
279 Test if compute instances started in different data centers
280 are able to talk to each other.
281 """
282 # create network
283 self.createNet(
284 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
285 autolinkswitches=True)
286 # setup links
287 self.net.addLink(self.dc[0], self.s[0])
288 self.net.addLink(self.dc[1], self.s[2])
289 # start Mininet network
290 self.startNet()
291 # add compute resources
292 vnf1 = self.dc[0].startCompute("vnf1")
293 vnf2 = self.dc[1].startCompute("vnf2")
294 # check number of running nodes
295 assert(len(self.getDockernetContainers()) == 2)
296 assert(len(self.net.hosts) == 2)
297 assert(len(self.net.switches) == 5)
298 # check compute list result
299 assert(len(self.dc[0].listCompute()) == 1)
300 assert(len(self.dc[1].listCompute()) == 1)
301 # check connectivity by using ping
302 assert(self.net.ping([vnf1, vnf2]) <= 0.0)
303 # stop Mininet network
304 self.stopNet()
305
306 def testInterleavedAddRemoveMultiDC(self):
307 """
308 Test multiple, interleaved add and remove operations and ensure
309 that always all expected compute instances are reachable.
310 """
311 # create network
312 self.createNet(
313 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
314 autolinkswitches=True)
315 # setup links
316 self.net.addLink(self.dc[0], self.s[0])
317 self.net.addLink(self.dc[1], self.s[2])
318 # start Mininet network
319 self.startNet()
320 # add compute resources
321 vnf1 = self.dc[0].startCompute("vnf1")
322 vnf2 = self.dc[1].startCompute("vnf2")
323 # check number of running nodes
324 assert(len(self.getDockernetContainers()) == 2)
325 assert(len(self.net.hosts) == 2)
326 assert(len(self.net.switches) == 5)
327 # check compute list result
328 assert(len(self.dc[0].listCompute()) == 1)
329 assert(len(self.dc[1].listCompute()) == 1)
330 # check connectivity by using ping
331 assert(self.net.ping([vnf1, vnf2]) <= 0.0)
332 # remove compute resources
333 self.dc[0].stopCompute("vnf1")
334 # check number of running nodes
335 assert(len(self.getDockernetContainers()) == 1)
336 assert(len(self.net.hosts) == 1)
337 assert(len(self.net.switches) == 5)
338 # check compute list result
339 assert(len(self.dc[0].listCompute()) == 0)
340 assert(len(self.dc[1].listCompute()) == 1)
341 # add compute resources
342 vnf3 = self.dc[0].startCompute("vnf3")
343 vnf4 = self.dc[0].startCompute("vnf4")
344 # check compute list result
345 assert(len(self.dc[0].listCompute()) == 2)
346 assert(len(self.dc[1].listCompute()) == 1)
347 assert(self.net.ping([vnf3, vnf2]) <= 0.0)
348 assert(self.net.ping([vnf4, vnf2]) <= 0.0)
349 # remove compute resources
350 self.dc[0].stopCompute("vnf3")
351 self.dc[0].stopCompute("vnf4")
352 self.dc[1].stopCompute("vnf2")
353 # check compute list result
354 assert(len(self.dc[0].listCompute()) == 0)
355 assert(len(self.dc[1].listCompute()) == 0)
356 # stop Mininet network
357 self.stopNet()
358
359 if __name__ == '__main__':
360 unittest.main()