1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # Neither the name of the SONATA-NFV, Paderborn University
17 # nor the names of its contributors may be used to endorse or promote
18 # products derived from this software without specific prior written
21 # This work has been performed in the framework of the SONATA project,
22 # funded by the European Commission under Grant number 671517 through
23 # the Horizon 2020 and 5G-PPP programmes. The authors would like to
24 # acknowledge the contributions of their colleagues of the SONATA
25 # partner consortium (www.sonata-nfv.eu).
29 from emuvim
.test
.base
import SimpleTestTopology
30 from emuvim
.dcemulator
.resourcemodel
import BaseResourceModel
, ResourceFlavor
, NotEnoughResourcesAvailable
, ResourceModelRegistrar
31 from emuvim
.dcemulator
.resourcemodel
.upb
.simple
import UpbSimpleCloudDcRM
, UpbOverprovisioningCloudDcRM
, UpbDummyRM
34 class testResourceModel(SimpleTestTopology
):
36 Test the general resource model API and functionality.
39 def testBaseResourceModelApi(self
):
41 Tast bare API without real resource madel.
44 r
= BaseResourceModel()
45 # check if default flavors are there
46 self
.assertTrue(len(r
._flavors
) == 5)
47 # check addFlavor functionality
48 f
= ResourceFlavor("test", {"testmetric": 42})
50 self
.assertTrue("test" in r
._flavors
)
51 self
.assertTrue(r
._flavors
.get("test").get("testmetric") == 42)
53 def testAddRmToDc(self
):
55 Test is allocate/free is called when a RM is added to a DC.
59 self
.createNet(nswitches
=0, ndatacenter
=1, nhosts
=2, ndockers
=0)
61 self
.net
.addLink(self
.dc
[0], self
.h
[0])
62 self
.net
.addLink(self
.h
[1], self
.dc
[0])
64 r
= BaseResourceModel()
65 self
.dc
[0].assignResourceModel(r
)
66 # start Mininet network
68 # check number of running nodes
69 self
.assertTrue(len(self
.getContainernetContainers()) == 0)
70 self
.assertTrue(len(self
.net
.hosts
) == 2)
71 self
.assertTrue(len(self
.net
.switches
) == 1)
72 # check resource model and resource model registrar
73 self
.assertTrue(self
.dc
[0]._resource
_model
is not None)
74 self
.assertTrue(len(self
.net
.rm_registrar
.resource_models
) == 1)
76 # check if alloc was called during startCompute
77 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
78 self
.dc
[0].startCompute("tc1")
80 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 1)
81 # check if free was called during stopCompute
82 self
.dc
[0].stopCompute("tc1")
83 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
84 # check connectivity by using ping
85 self
.assertTrue(self
.net
.ping([self
.h
[0], self
.h
[1]]) <= 0.0)
86 # stop Mininet network
90 def createDummyContainerObject(name
, flavor
):
92 class DummyContainer(object):
95 # take defaukt values from son-emu
96 self
.resources
= dict(
102 # self.cpu_period = self.resources['cpu_period']
103 # self.cpu_quota = self.resources['cpu_quota']
104 # self.mem_limit = self.resources['mem_limit']
105 # self.memswap_limit = self.resources['memswap_limit']
107 def updateCpuLimit(self
, cpu_period
, cpu_quota
):
108 self
.resources
['cpu_period'] = cpu_period
109 self
.resources
['cpu_quota'] = cpu_quota
111 def updateMemoryLimit(self
, mem_limit
):
112 self
.resources
['mem_limit'] = mem_limit
116 d
.flavor_name
= flavor
120 class testUpbSimpleCloudDcRM(SimpleTestTopology
):
122 Test the UpbSimpleCloudDc resource model.
125 def testAllocationComputations(self
):
127 Test the allocation procedures and correct calculations.
135 # create dummy resource model environment
136 reg
= ResourceModelRegistrar(
137 dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
138 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
139 reg
.register("test_dc", rm
)
141 c1
= createDummyContainerObject("c1", flavor
="tiny")
142 rm
.allocate(c1
) # calculate allocation
143 # validate compute result
144 self
.assertEqual(float(
145 c1
.resources
['cpu_quota']) / c1
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 0.5)
146 # validate memory result
148 float(c1
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 32)
150 c2
= createDummyContainerObject("c2", flavor
="small")
151 rm
.allocate(c2
) # calculate allocation
152 # validate compute result
153 self
.assertEqual(float(
154 c2
.resources
['cpu_quota']) / c2
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1)
155 # validate memory result
157 float(c2
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 128)
159 c3
= createDummyContainerObject("c3", flavor
="medium")
160 rm
.allocate(c3
) # calculate allocation
161 # validate compute result
162 self
.assertEqual(float(
163 c3
.resources
['cpu_quota']) / c3
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 4)
164 # validate memory result
166 float(c3
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 256)
168 c4
= createDummyContainerObject("c4", flavor
="large")
169 rm
.allocate(c4
) # calculate allocation
170 # validate compute result
171 self
.assertEqual(float(
172 c4
.resources
['cpu_quota']) / c4
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 8)
173 # validate memory result
175 float(c4
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 512)
177 c5
= createDummyContainerObject("c5", flavor
="xlarge")
178 rm
.allocate(c5
) # calculate allocation
179 # validate compute result
180 self
.assertEqual(float(
181 c5
.resources
['cpu_quota']) / c5
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 16)
182 # validate memory result
184 float(c5
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 1024)
186 def testAllocationCpuLimit(self
):
188 Test CPU allocation limit
196 # create dummy resource model environment
197 reg
= ResourceModelRegistrar(
198 dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
199 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
200 reg
.register("test_dc", rm
)
202 # test over provisioning exeption
205 c6
= createDummyContainerObject("c6", flavor
="xlarge")
206 c7
= createDummyContainerObject("c7", flavor
="xlarge")
207 c8
= createDummyContainerObject("c8", flavor
="xlarge")
208 c9
= createDummyContainerObject("c9", flavor
="xlarge")
209 rm
.allocate(c6
) # calculate allocation
210 rm
.allocate(c7
) # calculate allocation
211 rm
.allocate(c8
) # calculate allocation
212 rm
.allocate(c9
) # calculate allocation
213 except NotEnoughResourcesAvailable
as e
:
214 self
.assertIn("Not enough compute", e
.message
)
216 self
.assertTrue(exception
)
218 def testAllocationMemLimit(self
):
220 Test MEM allocation limit
228 # create dummy resource model environment
229 reg
= ResourceModelRegistrar(
230 dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
231 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
232 reg
.register("test_dc", rm
)
234 # test over provisioning exeption
237 c6
= createDummyContainerObject("c6", flavor
="xlarge")
238 c7
= createDummyContainerObject("c7", flavor
="xlarge")
239 c8
= createDummyContainerObject("c8", flavor
="xlarge")
240 rm
.allocate(c6
) # calculate allocation
241 rm
.allocate(c7
) # calculate allocation
242 rm
.allocate(c8
) # calculate allocation
243 except NotEnoughResourcesAvailable
as e
:
244 self
.assertIn("Not enough memory", e
.message
)
246 self
.assertTrue(exception
)
250 Test the free procedure.
253 # create dummy resource model environment
254 reg
= ResourceModelRegistrar(
255 dc_emulation_max_cpu
=1.0, dc_emulation_max_mem
=512)
256 rm
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
257 reg
.register("test_dc", rm
)
258 c1
= createDummyContainerObject("c6", flavor
="tiny")
259 rm
.allocate(c1
) # calculate allocation
260 self
.assertTrue(rm
.dc_alloc_cu
== 0.5)
262 self
.assertTrue(rm
.dc_alloc_cu
== 0)
264 @unittest.skipIf(os
.environ
.get("SON_EMU_IN_DOCKER") is not None,
265 "skipping test when running inside Docker container")
266 def testInRealTopo(self
):
268 Start a real container and check if limitations are really passed down to Conteinernet.
272 self
.createNet(nswitches
=0, ndatacenter
=1, nhosts
=2, ndockers
=0)
274 self
.net
.addLink(self
.dc
[0], self
.h
[0])
275 self
.net
.addLink(self
.h
[1], self
.dc
[0])
277 r
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
278 self
.dc
[0].assignResourceModel(r
)
279 # start Mininet network
281 # check number of running nodes
282 self
.assertTrue(len(self
.getContainernetContainers()) == 0)
283 self
.assertTrue(len(self
.net
.hosts
) == 2)
284 self
.assertTrue(len(self
.net
.switches
) == 1)
285 # check resource model and resource model registrar
286 self
.assertTrue(self
.dc
[0]._resource
_model
is not None)
287 self
.assertTrue(len(self
.net
.rm_registrar
.resource_models
) == 1)
289 # check if alloc was called during startCompute
290 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
291 tc1
= self
.dc
[0].startCompute("tc1", flavor_name
="tiny")
293 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 1)
295 # check if there is a real limitation set for containers cgroup
296 # deactivated for now, seems not to work in docker-in-docker setup used
299 float(tc1
.resources
['cpu_quota']) / tc1
.resources
['cpu_period'], 0.005)
301 # check if free was called during stopCompute
302 self
.dc
[0].stopCompute("tc1")
303 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
304 # check connectivity by using ping
305 self
.assertTrue(self
.net
.ping([self
.h
[0], self
.h
[1]]) <= 0.0)
306 # stop Mininet network
310 class testUpbOverprovisioningCloudDcRM(SimpleTestTopology
):
312 Test the UpbOverprovisioningCloudDc resource model.
315 def testAllocationComputations(self
):
317 Test the allocation procedures and correct calculations.
325 # create dummy resource model environment
326 reg
= ResourceModelRegistrar(
327 dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
328 rm
= UpbOverprovisioningCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
329 reg
.register("test_dc", rm
)
331 c1
= createDummyContainerObject("c1", flavor
="small")
332 rm
.allocate(c1
) # calculate allocation
333 self
.assertAlmostEqual(float(
334 c1
.resources
['cpu_quota']) / c1
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1.0, places
=5)
335 self
.assertAlmostEqual(
336 float(c1
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 128)
337 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
339 c2
= createDummyContainerObject("c2", flavor
="small")
340 rm
.allocate(c2
) # calculate allocation
341 self
.assertAlmostEqual(float(
342 c2
.resources
['cpu_quota']) / c2
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1.0, places
=5)
343 self
.assertAlmostEqual(
344 float(c2
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 128)
345 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
347 c3
= createDummyContainerObject("c3", flavor
="small")
348 rm
.allocate(c3
) # calculate allocation
349 self
.assertAlmostEqual(float(
350 c3
.resources
['cpu_quota']) / c3
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1.0, places
=5)
351 self
.assertAlmostEqual(
352 float(c3
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 128)
353 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
355 # from this container onwards, we should go to over provisioning mode:
356 c4
= createDummyContainerObject("c4", flavor
="small")
357 rm
.allocate(c4
) # calculate allocation
358 self
.assertAlmostEqual(float(
359 c4
.resources
['cpu_quota']) / c4
.resources
['cpu_period'], E_CPU
/ MAX_CU
* (float(3) / 4), places
=5)
360 self
.assertAlmostEqual(float(
361 c4
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 128, places
=5)
362 self
.assertAlmostEqual(rm
.cpu_op_factor
, 0.75)
364 c5
= createDummyContainerObject("c5", flavor
="small")
365 rm
.allocate(c5
) # calculate allocation
366 self
.assertAlmostEqual(float(
367 c5
.resources
['cpu_quota']) / c5
.resources
['cpu_period'], E_CPU
/ MAX_CU
* (float(3) / 5), places
=5)
368 self
.assertAlmostEqual(
369 float(c5
.resources
['mem_limit'] / 1024 / 1024), float(E_MEM
) / MAX_MU
* 128)
370 self
.assertAlmostEqual(rm
.cpu_op_factor
, 0.6)
373 class testUpbDummyRM(SimpleTestTopology
):
375 Test the UpbDummyRM resource model.
378 def testAllocationComputations(self
):
380 Test the allocation procedures and correct calculations.
388 # create dummy resource model environment
389 reg
= ResourceModelRegistrar(
390 dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
391 rm
= UpbDummyRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
392 reg
.register("test_dc", rm
)
394 c1
= createDummyContainerObject("c1", flavor
="small")
395 rm
.allocate(c1
) # calculate allocation
396 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 1)
398 c2
= createDummyContainerObject("c2", flavor
="small")
399 rm
.allocate(c2
) # calculate allocation
400 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 2)