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