blob: 5fbd172e2ce85b5a761b552d29e377bbdf25f819 [file] [log] [blame]
peustermc89ba382016-07-08 13:46:32 +02001"""
2Copyright (c) 2015 SONATA-NFV
3ALL RIGHTS RESERVED.
4
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17Neither the name of the SONATA-NFV [, ANY ADDITIONAL AFFILIATION]
18nor the names of its contributors may be used to endorse or promote
19products derived from this software without specific prior written
20permission.
21
22This work has been performed in the framework of the SONATA project,
23funded by the European Commission under Grant number 671517 through
24the Horizon 2020 and 5G-PPP programmes. The authors would like to
25acknowledge the contributions of their colleagues of the SONATA
26partner consortium (www.sonata-nfv.eu).
27"""
28
peusterm43485a22016-03-14 11:18:37 +010029import time
peusterm3055e702016-04-16 16:48:12 +020030import os
peustermc1305232016-05-11 16:14:22 +020031import unittest
peusterm5c6475c2016-03-13 12:54:11 +010032from emuvim.test.base import SimpleTestTopology
peusterma41f7862016-04-27 11:01:24 +020033from emuvim.dcemulator.resourcemodel import BaseResourceModel, ResourceFlavor, NotEnoughResourcesAvailable, ResourceModelRegistrar
peusterm8687cb72016-04-28 20:32:36 +020034from emuvim.dcemulator.resourcemodel.upb.simple import UpbSimpleCloudDcRM, UpbOverprovisioningCloudDcRM, UpbDummyRM
peusterma41f7862016-04-27 11:01:24 +020035
peusterm5c6475c2016-03-13 12:54:11 +010036
37
38class testResourceModel(SimpleTestTopology):
peustermbdcf2d22016-03-25 12:14:15 +010039 """
40 Test the general resource model API and functionality.
41 """
peusterm5c6475c2016-03-13 12:54:11 +010042
43 def testBaseResourceModelApi(self):
peustermbdcf2d22016-03-25 12:14:15 +010044 """
45 Tast bare API without real resource madel.
46 :return:
47 """
peusterm43485a22016-03-14 11:18:37 +010048 r = BaseResourceModel()
49 # check if default flavors are there
peustermbdcf2d22016-03-25 12:14:15 +010050 self.assertTrue(len(r._flavors) == 5)
peusterm43485a22016-03-14 11:18:37 +010051 # check addFlavor functionality
52 f = ResourceFlavor("test", {"testmetric": 42})
53 r.addFlavour(f)
peustermbdcf2d22016-03-25 12:14:15 +010054 self.assertTrue("test" in r._flavors)
55 self.assertTrue(r._flavors.get("test").get("testmetric") == 42)
peusterm5c6475c2016-03-13 12:54:11 +010056
57 def testAddRmToDc(self):
peustermbdcf2d22016-03-25 12:14:15 +010058 """
59 Test is allocate/free is called when a RM is added to a DC.
60 :return:
61 """
peusterm5c6475c2016-03-13 12:54:11 +010062 # create network
63 self.createNet(nswitches=0, ndatacenter=1, nhosts=2, ndockers=0)
64 # setup links
65 self.net.addLink(self.dc[0], self.h[0])
66 self.net.addLink(self.h[1], self.dc[0])
67 # add resource model
68 r = BaseResourceModel()
69 self.dc[0].assignResourceModel(r)
70 # start Mininet network
71 self.startNet()
72 # check number of running nodes
peusterm5877ea22016-05-11 13:44:59 +020073 self.assertTrue(len(self.getContainernetContainers()) == 0)
peustermbdcf2d22016-03-25 12:14:15 +010074 self.assertTrue(len(self.net.hosts) == 2)
75 self.assertTrue(len(self.net.switches) == 1)
peusterm5c6475c2016-03-13 12:54:11 +010076 # check resource model and resource model registrar
peustermbdcf2d22016-03-25 12:14:15 +010077 self.assertTrue(self.dc[0]._resource_model is not None)
78 self.assertTrue(len(self.net.rm_registrar.resource_models) == 1)
peusterm43485a22016-03-14 11:18:37 +010079
80 # check if alloc was called during startCompute
peustermd18559d2016-04-16 04:59:23 +020081 self.assertTrue(len(r._allocated_compute_instances) == 0)
peusterm43485a22016-03-14 11:18:37 +010082 self.dc[0].startCompute("tc1")
83 time.sleep(1)
peustermd18559d2016-04-16 04:59:23 +020084 self.assertTrue(len(r._allocated_compute_instances) == 1)
peusterm43485a22016-03-14 11:18:37 +010085 # check if free was called during stopCompute
86 self.dc[0].stopCompute("tc1")
peustermd18559d2016-04-16 04:59:23 +020087 self.assertTrue(len(r._allocated_compute_instances) == 0)
peusterm5c6475c2016-03-13 12:54:11 +010088 # check connectivity by using ping
peustermbdcf2d22016-03-25 12:14:15 +010089 self.assertTrue(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
peusterm5c6475c2016-03-13 12:54:11 +010090 # stop Mininet network
91 self.stopNet()
peusterm279565d2016-03-19 10:36:52 +010092
93
peustermd18559d2016-04-16 04:59:23 +020094def createDummyContainerObject(name, flavor):
95
96 class DummyContainer(object):
97
98 def __init__(self):
stevenvanrossem33d76892017-02-13 00:13:37 +010099 # take defaukt values from son-emu
100 # self.cpu_period = -1
peustermd18559d2016-04-16 04:59:23 +0200101 self.cpu_quota = -1
stevenvanrossem33d76892017-02-13 00:13:37 +0100102 # self.mem_limit = -1
103 # self.memswap_limit = -1
peustermd18559d2016-04-16 04:59:23 +0200104
105 def updateCpuLimit(self, cpu_period, cpu_quota):
106 self.cpu_period = cpu_period
107 self.cpu_quota = cpu_quota
108
109 def updateMemoryLimit(self, mem_limit):
110 self.mem_limit = mem_limit
111
112 d = DummyContainer()
113 d.name = name
114 d.flavor_name = flavor
115 return d
116
117
118
119
peusterm279565d2016-03-19 10:36:52 +0100120class testUpbSimpleCloudDcRM(SimpleTestTopology):
121 """
122 Test the UpbSimpleCloudDc resource model.
123 """
peustermbdcf2d22016-03-25 12:14:15 +0100124
peusterm72fc3732016-04-26 19:48:43 +0200125 def testAllocationComputations(self):
peustermbdcf2d22016-03-25 12:14:15 +0100126 """
127 Test the allocation procedures and correct calculations.
128 :return:
129 """
peusterm279565d2016-03-19 10:36:52 +0100130 # config
131 E_CPU = 1.0
132 MAX_CU = 100
peusterm972a9f02016-03-25 14:58:05 +0100133 E_MEM = 512
134 MAX_MU = 2048
peusterm279565d2016-03-19 10:36:52 +0100135 # create dummy resource model environment
peusterm972a9f02016-03-25 14:58:05 +0100136 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
137 rm = UpbSimpleCloudDcRM(max_cu=MAX_CU, max_mu=MAX_MU)
peusterm279565d2016-03-19 10:36:52 +0100138 reg.register("test_dc", rm)
139
peustermd18559d2016-04-16 04:59:23 +0200140 c1 = createDummyContainerObject("c1", flavor="tiny")
141 rm.allocate(c1) # calculate allocation
142 self.assertEqual(float(c1.cpu_quota) / c1.cpu_period, E_CPU / MAX_CU * 0.5) # validate compute result
143 self.assertEqual(float(c1.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 32) # validate memory result
peusterm279565d2016-03-19 10:36:52 +0100144
peustermd18559d2016-04-16 04:59:23 +0200145 c2 = createDummyContainerObject("c2", flavor="small")
146 rm.allocate(c2) # calculate allocation
147 self.assertEqual(float(c2.cpu_quota) / c2.cpu_period, E_CPU / MAX_CU * 1) # validate compute result
148 self.assertEqual(float(c2.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 128) # validate memory result
peusterm279565d2016-03-19 10:36:52 +0100149
peustermd18559d2016-04-16 04:59:23 +0200150 c3 = createDummyContainerObject("c3", flavor="medium")
peusterm72fc3732016-04-26 19:48:43 +0200151 rm.allocate(c3) # calculate allocation
peustermd18559d2016-04-16 04:59:23 +0200152 self.assertEqual(float(c3.cpu_quota) / c3.cpu_period, E_CPU / MAX_CU * 4) # validate compute result
153 self.assertEqual(float(c3.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 256) # validate memory result
peusterm279565d2016-03-19 10:36:52 +0100154
peustermd18559d2016-04-16 04:59:23 +0200155 c4 = createDummyContainerObject("c4", flavor="large")
156 rm.allocate(c4) # calculate allocation
157 self.assertEqual(float(c4.cpu_quota) / c4.cpu_period, E_CPU / MAX_CU * 8) # validate compute result
158 self.assertEqual(float(c4.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 512) # validate memory result
159
peustermd18559d2016-04-16 04:59:23 +0200160 c5 = createDummyContainerObject("c5", flavor="xlarge")
161 rm.allocate(c5) # calculate allocation
162 self.assertEqual(float(c5.cpu_quota) / c5.cpu_period, E_CPU / MAX_CU * 16) # validate compute result
163 self.assertEqual(float(c5.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 1024) # validate memory result
164
peusterm279565d2016-03-19 10:36:52 +0100165
peusterm972a9f02016-03-25 14:58:05 +0100166 def testAllocationCpuLimit(self):
167 """
168 Test CPU allocation limit
169 :return:
170 """
171 # config
172 E_CPU = 1.0
peusterm60bf8b82016-04-06 14:12:35 +0200173 MAX_CU = 40
peusterm972a9f02016-03-25 14:58:05 +0100174 E_MEM = 512
175 MAX_MU = 4096
176 # create dummy resource model environment
177 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
178 rm = UpbSimpleCloudDcRM(max_cu=MAX_CU, max_mu=MAX_MU)
179 reg.register("test_dc", rm)
180
peusterm279565d2016-03-19 10:36:52 +0100181 # test over provisioning exeption
182 exception = False
183 try:
peustermd18559d2016-04-16 04:59:23 +0200184 c6 = createDummyContainerObject("c6", flavor="xlarge")
185 c7 = createDummyContainerObject("c7", flavor="xlarge")
186 c8 = createDummyContainerObject("c8", flavor="xlarge")
187 c9 = createDummyContainerObject("c9", flavor="xlarge")
188 rm.allocate(c6) # calculate allocation
189 rm.allocate(c7) # calculate allocation
190 rm.allocate(c8) # calculate allocation
191 rm.allocate(c9) # calculate allocation
peusterma41f7862016-04-27 11:01:24 +0200192 except NotEnoughResourcesAvailable as e:
peusterm972a9f02016-03-25 14:58:05 +0100193 self.assertIn("Not enough compute", e.message)
194 exception = True
195 self.assertTrue(exception)
196
197 def testAllocationMemLimit(self):
198 """
199 Test MEM allocation limit
200 :return:
201 """
202 # config
203 E_CPU = 1.0
204 MAX_CU = 500
205 E_MEM = 512
206 MAX_MU = 2048
207 # create dummy resource model environment
208 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
209 rm = UpbSimpleCloudDcRM(max_cu=MAX_CU, max_mu=MAX_MU)
210 reg.register("test_dc", rm)
211
212 # test over provisioning exeption
213 exception = False
214 try:
peustermd18559d2016-04-16 04:59:23 +0200215 c6 = createDummyContainerObject("c6", flavor="xlarge")
216 c7 = createDummyContainerObject("c7", flavor="xlarge")
217 c8 = createDummyContainerObject("c8", flavor="xlarge")
218 rm.allocate(c6) # calculate allocation
219 rm.allocate(c7) # calculate allocation
220 rm.allocate(c8) # calculate allocation
peusterma41f7862016-04-27 11:01:24 +0200221 except NotEnoughResourcesAvailable as e:
peusterm972a9f02016-03-25 14:58:05 +0100222 self.assertIn("Not enough memory", e.message)
peusterm279565d2016-03-19 10:36:52 +0100223 exception = True
peustermbdcf2d22016-03-25 12:14:15 +0100224 self.assertTrue(exception)
peusterm279565d2016-03-19 10:36:52 +0100225
226 def testFree(self):
peustermbdcf2d22016-03-25 12:14:15 +0100227 """
228 Test the free procedure.
229 :return:
230 """
peusterm279565d2016-03-19 10:36:52 +0100231 # config
232 E_CPU = 1.0
233 MAX_CU = 100
234 # create dummy resource model environment
peusterm972a9f02016-03-25 14:58:05 +0100235 reg = ResourceModelRegistrar(dc_emulation_max_cpu=1.0, dc_emulation_max_mem=512)
peusterm279565d2016-03-19 10:36:52 +0100236 rm = UpbSimpleCloudDcRM(max_cu=100, max_mu=100)
237 reg.register("test_dc", rm)
peustermd18559d2016-04-16 04:59:23 +0200238 c1 = createDummyContainerObject("c6", flavor="tiny")
239 rm.allocate(c1) # calculate allocation
peusterm60bf8b82016-04-06 14:12:35 +0200240 self.assertTrue(rm.dc_alloc_cu == 0.5)
peustermd18559d2016-04-16 04:59:23 +0200241 rm.free(c1)
peustermbdcf2d22016-03-25 12:14:15 +0100242 self.assertTrue(rm.dc_alloc_cu == 0)
243
peustermc1305232016-05-11 16:14:22 +0200244 @unittest.skipIf(os.environ.get("SON_EMU_IN_DOCKER") is not None,
245 "skipping test when running inside Docker container")
peustermbdcf2d22016-03-25 12:14:15 +0100246 def testInRealTopo(self):
247 """
peusterm5877ea22016-05-11 13:44:59 +0200248 Start a real container and check if limitations are really passed down to Conteinernet.
peustermbdcf2d22016-03-25 12:14:15 +0100249 :return:
250 """
251 # create network
252 self.createNet(nswitches=0, ndatacenter=1, nhosts=2, ndockers=0)
253 # setup links
254 self.net.addLink(self.dc[0], self.h[0])
255 self.net.addLink(self.h[1], self.dc[0])
256 # add resource model
257 r = UpbSimpleCloudDcRM(max_cu=100, max_mu=100)
258 self.dc[0].assignResourceModel(r)
259 # start Mininet network
260 self.startNet()
261 # check number of running nodes
peusterm5877ea22016-05-11 13:44:59 +0200262 self.assertTrue(len(self.getContainernetContainers()) == 0)
peustermbdcf2d22016-03-25 12:14:15 +0100263 self.assertTrue(len(self.net.hosts) == 2)
264 self.assertTrue(len(self.net.switches) == 1)
265 # check resource model and resource model registrar
266 self.assertTrue(self.dc[0]._resource_model is not None)
267 self.assertTrue(len(self.net.rm_registrar.resource_models) == 1)
268
269 # check if alloc was called during startCompute
peustermd18559d2016-04-16 04:59:23 +0200270 self.assertTrue(len(r._allocated_compute_instances) == 0)
peustermbdcf2d22016-03-25 12:14:15 +0100271 tc1 = self.dc[0].startCompute("tc1", flavor_name="tiny")
272 time.sleep(1)
peustermd18559d2016-04-16 04:59:23 +0200273 self.assertTrue(len(r._allocated_compute_instances) == 1)
peustermbdcf2d22016-03-25 12:14:15 +0100274
275 # check if there is a real limitation set for containers cgroup
peusterm9349c872016-04-16 06:36:42 +0200276 # deactivated for now, seems not to work in docker-in-docker setup used in CI
peusterm3055e702016-04-16 16:48:12 +0200277 self.assertEqual(float(tc1.cpu_quota)/tc1.cpu_period, 0.005)
peustermbdcf2d22016-03-25 12:14:15 +0100278
279 # check if free was called during stopCompute
280 self.dc[0].stopCompute("tc1")
peustermd18559d2016-04-16 04:59:23 +0200281 self.assertTrue(len(r._allocated_compute_instances) == 0)
peustermbdcf2d22016-03-25 12:14:15 +0100282 # check connectivity by using ping
283 self.assertTrue(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
284 # stop Mininet network
285 self.stopNet()
peusterm279565d2016-03-19 10:36:52 +0100286
287
peusterm72fc3732016-04-26 19:48:43 +0200288class testUpbOverprovisioningCloudDcRM(SimpleTestTopology):
289 """
290 Test the UpbOverprovisioningCloudDc resource model.
291 """
292
293 def testAllocationComputations(self):
294 """
295 Test the allocation procedures and correct calculations.
296 :return:
297 """
298 # config
299 E_CPU = 1.0
300 MAX_CU = 3
301 E_MEM = 512
302 MAX_MU = 2048
303 # create dummy resource model environment
304 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
305 rm = UpbOverprovisioningCloudDcRM(max_cu=MAX_CU, max_mu=MAX_MU)
306 reg.register("test_dc", rm)
307
308 c1 = createDummyContainerObject("c1", flavor="small")
309 rm.allocate(c1) # calculate allocation
310 self.assertAlmostEqual(float(c1.cpu_quota) / c1.cpu_period, E_CPU / MAX_CU * 1.0, places=5)
311 self.assertAlmostEqual(float(c1.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 128)
312 self.assertAlmostEqual(rm.cpu_op_factor, 1.0)
313
314 c2 = createDummyContainerObject("c2", flavor="small")
315 rm.allocate(c2) # calculate allocation
316 self.assertAlmostEqual(float(c2.cpu_quota) / c2.cpu_period, E_CPU / MAX_CU * 1.0, places=5)
317 self.assertAlmostEqual(float(c2.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 128)
318 self.assertAlmostEqual(rm.cpu_op_factor, 1.0)
319
320 c3 = createDummyContainerObject("c3", flavor="small")
321 rm.allocate(c3) # calculate allocation
322 self.assertAlmostEqual(float(c3.cpu_quota) / c3.cpu_period, E_CPU / MAX_CU * 1.0, places=5)
323 self.assertAlmostEqual(float(c3.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 128)
324 self.assertAlmostEqual(rm.cpu_op_factor, 1.0)
325
326 # from this container onwards, we should go to over provisioning mode:
327 c4 = createDummyContainerObject("c4", flavor="small")
328 rm.allocate(c4) # calculate allocation
329 self.assertAlmostEqual(float(c4.cpu_quota) / c4.cpu_period, E_CPU / MAX_CU * (float(3) / 4), places=5)
330 self.assertAlmostEqual(float(c4.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 128, places=5)
331 self.assertAlmostEqual(rm.cpu_op_factor, 0.75)
332
333 c5 = createDummyContainerObject("c5", flavor="small")
334 rm.allocate(c5) # calculate allocation
335 self.assertAlmostEqual(float(c5.cpu_quota) / c5.cpu_period, E_CPU / MAX_CU * (float(3) / 5), places=5)
336 self.assertAlmostEqual(float(c5.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 128)
337 self.assertAlmostEqual(rm.cpu_op_factor, 0.6)
338
339
peusterm8687cb72016-04-28 20:32:36 +0200340class testUpbDummyRM(SimpleTestTopology):
341 """
342 Test the UpbDummyRM resource model.
343 """
344
345 def testAllocationComputations(self):
346 """
347 Test the allocation procedures and correct calculations.
348 :return:
349 """
350 # config
351 E_CPU = 1.0
352 MAX_CU = 3
353 E_MEM = 512
354 MAX_MU = 2048
355 # create dummy resource model environment
356 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
357 rm = UpbDummyRM(max_cu=MAX_CU, max_mu=MAX_MU)
358 reg.register("test_dc", rm)
359
360 c1 = createDummyContainerObject("c1", flavor="small")
361 rm.allocate(c1) # calculate allocation
362 self.assertEqual(len(rm._allocated_compute_instances), 1)
363
364 c2 = createDummyContainerObject("c2", flavor="small")
365 rm.allocate(c2) # calculate allocation
366 self.assertEqual(len(rm._allocated_compute_instances), 2)
peusterm279565d2016-03-19 10:36:52 +0100367