Merge pull request #1 from mpeuster/master
[osm/vim-emu.git] / 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 dcemulator.net import DCNetwork
15 from 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(self.net.addDatacenter('dc%d' % i))
59 # add some hosts
60 for i in range(0, nhosts):
61 self.h.append(self.net.addHost('h%d' % i))
62 # add some dockers
63 for i in range(0, ndockers):
64 self.d.append(self.net.addDocker('d%d' % i, dimage="ubuntu"))
65
66 def startNet(self):
67 self.net.start()
68
69 def stopNet(self):
70 self.net.stop()
71
72 def getDockerCli(self):
73 """
74 Helper to interact with local docker instance.
75 """
76 if self.docker_cli is None:
77 self.docker_cli = docker.Client(
78 base_url='unix://var/run/docker.sock')
79 return self.docker_cli
80
81 @staticmethod
82 def setUp():
83 pass
84
85 @staticmethod
86 def tearDown():
87 cleanup()
88 # make sure that all pending docker containers are killed
89 with open(os.devnull, 'w') as devnull:
90 subprocess.call(
91 "sudo docker rm -f $(sudo docker ps -a -q)",
92 stdout=devnull,
93 stderr=devnull,
94 shell=True)
95
96
97 #@unittest.skip("disabled topology tests for development")
98 class testEmulatorTopology( simpleTestTopology ):
99 """
100 Tests to check the topology API of the emulator.
101 """
102
103 def testSingleDatacenter(self):
104 """
105 Create a single data center and add check if its switch is up
106 by using manually added hosts. Tests especially the
107 data center specific addLink method.
108 """
109 # create network
110 self.createNet(nswitches=0, ndatacenter=1, nhosts=2, ndockers=0)
111 # setup links
112 self.net.addLink(self.dc[0], self.h[0])
113 self.net.addLink(self.h[1], self.dc[0])
114 # start Mininet network
115 self.startNet()
116 # check number of running nodes
117 assert(len(self.getDockerCli().containers()) == 0)
118 assert(len(self.net.hosts) == 2)
119 assert(len(self.net.switches) == 1)
120 # check connectivity by using ping
121 assert(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
122 # stop Mininet network
123 self.stopNet()
124
125 def testMultipleDatacenterDirect(self):
126 """
127 Create a two data centers and interconnect them.
128 """
129 # create network
130 self.createNet(nswitches=0, ndatacenter=2, nhosts=2, ndockers=0)
131 # setup links
132 self.net.addLink(self.dc[0], self.h[0])
133 self.net.addLink(self.h[1], self.dc[1])
134 self.net.addLink(self.dc[0], self.dc[1])
135 # start Mininet network
136 self.startNet()
137 # check number of running nodes
138 assert(len(self.getDockerCli().containers()) == 0)
139 assert(len(self.net.hosts) == 2)
140 assert(len(self.net.switches) == 2)
141 # check connectivity by using ping
142 assert(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
143 # stop Mininet network
144 self.stopNet()
145
146 def testMultipleDatacenterWithIntermediateSwitches(self):
147 """
148 Create a two data centers and interconnect them with additional
149 switches between them.
150 """
151 # create network
152 self.createNet(
153 nswitches=3, ndatacenter=2, nhosts=2, ndockers=0,
154 autolinkswitches=True)
155 # setup links
156 self.net.addLink(self.dc[0], self.h[0])
157 self.net.addLink(self.h[1], self.dc[1])
158 self.net.addLink(self.dc[0], self.s[0])
159 self.net.addLink(self.s[2], self.dc[1])
160 # start Mininet network
161 self.startNet()
162 # check number of running nodes
163 assert(len(self.getDockerCli().containers()) == 0)
164 assert(len(self.net.hosts) == 2)
165 assert(len(self.net.switches) == 5)
166 # check connectivity by using ping
167 assert(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
168 # stop Mininet network
169 self.stopNet()
170
171
172 #@unittest.skip("disabled compute tests for development")
173 class testEmulatorCompute( simpleTestTopology ):
174 """
175 Tests to check the emulator's API to add and remove
176 compute resources at runtime.
177 """
178
179 def testAddSingleComputeSingleDC(self):
180 """
181 Adds a single compute instance to
182 a single DC and checks its connectivity with a
183 manually added host.
184 """
185 # create network
186 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
187 # setup links
188 self.net.addLink(self.dc[0], self.h[0])
189 # start Mininet network
190 self.startNet()
191 # add compute resources
192 vnf1 = self.dc[0].startCompute("vnf1")
193 # check number of running nodes
194 assert(len(self.getDockerCli().containers()) == 1)
195 assert(len(self.net.hosts) == 2)
196 assert(len(self.net.switches) == 1)
197 # check compute list result
198 assert(len(self.dc[0].listCompute()) == 1)
199 assert(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
200 assert(self.dc[0].listCompute()[0].name == "vnf1")
201 # check connectivity by using ping
202 assert(self.net.ping([self.h[0], vnf1]) <= 0.0)
203 # stop Mininet network
204 self.stopNet()
205
206 def testRemoveSingleComputeSingleDC(self):
207 """
208 Test stop method for compute instances.
209 Check that the instance is really removed.
210 """
211 # create network
212 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
213 # setup links
214 self.net.addLink(self.dc[0], self.h[0])
215 # start Mininet network
216 self.startNet()
217 # add compute resources
218 vnf1 = self.dc[0].startCompute("vnf1")
219 # check number of running nodes
220 assert(len(self.getDockerCli().containers()) == 1)
221 assert(len(self.net.hosts) == 2)
222 assert(len(self.net.switches) == 1)
223 # check compute list result
224 assert(len(self.dc[0].listCompute()) == 1)
225 # check connectivity by using ping
226 assert(self.net.ping([self.h[0], vnf1]) <= 0.0)
227 # remove compute resources
228 self.dc[0].stopCompute("vnf1")
229 # check number of running nodes
230 assert(len(self.getDockerCli().containers()) == 0)
231 assert(len(self.net.hosts) == 1)
232 assert(len(self.net.switches) == 1)
233 # check compute list result
234 assert(len(self.dc[0].listCompute()) == 0)
235 # stop Mininet network
236 self.stopNet()
237
238 def testGetStatusSingleComputeSingleDC(self):
239 """
240 Check if the getStatus functionality of EmulatorCompute
241 objects works well.
242 """
243 # create network
244 self.createNet(nswitches=0, ndatacenter=1, nhosts=1, ndockers=0)
245 # setup links
246 self.net.addLink(self.dc[0], self.h[0])
247 # start Mininet network
248 self.startNet()
249 # add compute resources
250 vnf1 = self.dc[0].startCompute("vnf1")
251 # check number of running nodes
252 assert(len(self.getDockerCli().containers()) == 1)
253 assert(len(self.net.hosts) == 2)
254 assert(len(self.net.switches) == 1)
255 # check compute list result
256 assert(len(self.dc[0].listCompute()) == 1)
257 assert(isinstance(self.dc[0].listCompute()[0], EmulatorCompute))
258 assert(self.dc[0].listCompute()[0].name == "vnf1")
259 # check connectivity by using ping
260 assert(self.net.ping([self.h[0], vnf1]) <= 0.0)
261 # check get status
262 s = self.dc[0].containers.get("vnf1").getStatus()
263 assert(s["name"] == "vnf1")
264 assert(s["state"]["Running"])
265 # stop Mininet network
266 self.stopNet()
267
268 def testConnectivityMultiDC(self):
269 """
270 Test if compute instances started in different data centers
271 are able to talk to each other.
272 """
273 # create network
274 self.createNet(
275 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
276 autolinkswitches=True)
277 # setup links
278 self.net.addLink(self.dc[0], self.s[0])
279 self.net.addLink(self.dc[1], self.s[2])
280 # start Mininet network
281 self.startNet()
282 # add compute resources
283 vnf1 = self.dc[0].startCompute("vnf1")
284 vnf2 = self.dc[1].startCompute("vnf2")
285 # check number of running nodes
286 assert(len(self.getDockerCli().containers()) == 2)
287 assert(len(self.net.hosts) == 2)
288 assert(len(self.net.switches) == 5)
289 # check compute list result
290 assert(len(self.dc[0].listCompute()) == 1)
291 assert(len(self.dc[1].listCompute()) == 1)
292 # check connectivity by using ping
293 assert(self.net.ping([vnf1, vnf2]) <= 0.0)
294 # stop Mininet network
295 self.stopNet()
296
297 def testInterleavedAddRemoveMultiDC(self):
298 """
299 Test multiple, interleaved add and remove operations and ensure
300 that always all expected compute instances are reachable.
301 """
302 # create network
303 self.createNet(
304 nswitches=3, ndatacenter=2, nhosts=0, ndockers=0,
305 autolinkswitches=True)
306 # setup links
307 self.net.addLink(self.dc[0], self.s[0])
308 self.net.addLink(self.dc[1], self.s[2])
309 # start Mininet network
310 self.startNet()
311 # add compute resources
312 vnf1 = self.dc[0].startCompute("vnf1")
313 vnf2 = self.dc[1].startCompute("vnf2")
314 # check number of running nodes
315 assert(len(self.getDockerCli().containers()) == 2)
316 assert(len(self.net.hosts) == 2)
317 assert(len(self.net.switches) == 5)
318 # check compute list result
319 assert(len(self.dc[0].listCompute()) == 1)
320 assert(len(self.dc[1].listCompute()) == 1)
321 # check connectivity by using ping
322 assert(self.net.ping([vnf1, vnf2]) <= 0.0)
323 # remove compute resources
324 self.dc[0].stopCompute("vnf1")
325 # check number of running nodes
326 assert(len(self.getDockerCli().containers()) == 1)
327 assert(len(self.net.hosts) == 1)
328 assert(len(self.net.switches) == 5)
329 # check compute list result
330 assert(len(self.dc[0].listCompute()) == 0)
331 assert(len(self.dc[1].listCompute()) == 1)
332 # add compute resources
333 vnf3 = self.dc[0].startCompute("vnf3")
334 vnf4 = self.dc[0].startCompute("vnf4")
335 # check compute list result
336 assert(len(self.dc[0].listCompute()) == 2)
337 assert(len(self.dc[1].listCompute()) == 1)
338 assert(self.net.ping([vnf3, vnf2]) <= 0.0)
339 assert(self.net.ping([vnf4, vnf2]) <= 0.0)
340 # remove compute resources
341 self.dc[0].stopCompute("vnf3")
342 self.dc[0].stopCompute("vnf4")
343 self.dc[1].stopCompute("vnf2")
344 # check compute list result
345 assert(len(self.dc[0].listCompute()) == 0)
346 assert(len(self.dc[1].listCompute()) == 0)
347 # stop Mininet network
348 self.stopNet()
349
350 if __name__ == '__main__':
351 unittest.main()