2 Copyright (c) 2015 SONATA-NFV
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
17 Neither the name of the SONATA-NFV [, ANY ADDITIONAL AFFILIATION]
18 nor the names of its contributors may be used to endorse or promote
19 products derived from this software without specific prior written
22 This work has been performed in the framework of the SONATA project,
23 funded by the European Commission under Grant number 671517 through
24 the Horizon 2020 and 5G-PPP programmes. The authors would like to
25 acknowledge the contributions of their colleagues of the SONATA
26 partner consortium (www.sonata-nfv.eu).
32 from emuvim
.test
.base
import SimpleTestTopology
33 from emuvim
.dcemulator
.resourcemodel
import BaseResourceModel
, ResourceFlavor
, NotEnoughResourcesAvailable
, ResourceModelRegistrar
34 from emuvim
.dcemulator
.resourcemodel
.upb
.simple
import UpbSimpleCloudDcRM
, UpbOverprovisioningCloudDcRM
, UpbDummyRM
38 class testResourceModel(SimpleTestTopology
):
40 Test the general resource model API and functionality.
43 def testBaseResourceModelApi(self
):
45 Tast bare API without real resource madel.
48 r
= BaseResourceModel()
49 # check if default flavors are there
50 self
.assertTrue(len(r
._flavors
) == 5)
51 # check addFlavor functionality
52 f
= ResourceFlavor("test", {"testmetric": 42})
54 self
.assertTrue("test" in r
._flavors
)
55 self
.assertTrue(r
._flavors
.get("test").get("testmetric") == 42)
57 def testAddRmToDc(self
):
59 Test is allocate/free is called when a RM is added to a DC.
63 self
.createNet(nswitches
=0, ndatacenter
=1, nhosts
=2, ndockers
=0)
65 self
.net
.addLink(self
.dc
[0], self
.h
[0])
66 self
.net
.addLink(self
.h
[1], self
.dc
[0])
68 r
= BaseResourceModel()
69 self
.dc
[0].assignResourceModel(r
)
70 # start Mininet network
72 # check number of running nodes
73 self
.assertTrue(len(self
.getContainernetContainers()) == 0)
74 self
.assertTrue(len(self
.net
.hosts
) == 2)
75 self
.assertTrue(len(self
.net
.switches
) == 1)
76 # check resource model and resource model registrar
77 self
.assertTrue(self
.dc
[0]._resource
_model
is not None)
78 self
.assertTrue(len(self
.net
.rm_registrar
.resource_models
) == 1)
80 # check if alloc was called during startCompute
81 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
82 self
.dc
[0].startCompute("tc1")
84 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 1)
85 # check if free was called during stopCompute
86 self
.dc
[0].stopCompute("tc1")
87 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
88 # check connectivity by using ping
89 self
.assertTrue(self
.net
.ping([self
.h
[0], self
.h
[1]]) <= 0.0)
90 # stop Mininet network
94 def createDummyContainerObject(name
, flavor
):
96 class DummyContainer(object):
102 self
.memswap_limit
= -1
104 def updateCpuLimit(self
, cpu_period
, cpu_quota
):
105 self
.cpu_period
= cpu_period
106 self
.cpu_quota
= cpu_quota
108 def updateMemoryLimit(self
, mem_limit
):
109 self
.mem_limit
= mem_limit
113 d
.flavor_name
= flavor
119 class testUpbSimpleCloudDcRM(SimpleTestTopology
):
121 Test the UpbSimpleCloudDc resource model.
124 def testAllocationComputations(self
):
126 Test the allocation procedures and correct calculations.
134 # create dummy resource model environment
135 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
136 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
137 reg
.register("test_dc", rm
)
139 c1
= createDummyContainerObject("c1", flavor
="tiny")
140 rm
.allocate(c1
) # calculate allocation
141 self
.assertEqual(float(c1
.cpu_quota
) / c1
.cpu_period
, E_CPU
/ MAX_CU
* 0.5) # validate compute result
142 self
.assertEqual(float(c1
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 32) # validate memory result
144 c2
= createDummyContainerObject("c2", flavor
="small")
145 rm
.allocate(c2
) # calculate allocation
146 self
.assertEqual(float(c2
.cpu_quota
) / c2
.cpu_period
, E_CPU
/ MAX_CU
* 1) # validate compute result
147 self
.assertEqual(float(c2
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 128) # validate memory result
149 c3
= createDummyContainerObject("c3", flavor
="medium")
150 rm
.allocate(c3
) # calculate allocation
151 self
.assertEqual(float(c3
.cpu_quota
) / c3
.cpu_period
, E_CPU
/ MAX_CU
* 4) # validate compute result
152 self
.assertEqual(float(c3
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 256) # validate memory result
154 c4
= createDummyContainerObject("c4", flavor
="large")
155 rm
.allocate(c4
) # calculate allocation
156 self
.assertEqual(float(c4
.cpu_quota
) / c4
.cpu_period
, E_CPU
/ MAX_CU
* 8) # validate compute result
157 self
.assertEqual(float(c4
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 512) # validate memory result
159 c5
= createDummyContainerObject("c5", flavor
="xlarge")
160 rm
.allocate(c5
) # calculate allocation
161 self
.assertEqual(float(c5
.cpu_quota
) / c5
.cpu_period
, E_CPU
/ MAX_CU
* 16) # validate compute result
162 self
.assertEqual(float(c5
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 1024) # validate memory result
165 def testAllocationCpuLimit(self
):
167 Test CPU allocation limit
175 # create dummy resource model environment
176 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
177 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
178 reg
.register("test_dc", rm
)
180 # test over provisioning exeption
183 c6
= createDummyContainerObject("c6", flavor
="xlarge")
184 c7
= createDummyContainerObject("c7", flavor
="xlarge")
185 c8
= createDummyContainerObject("c8", flavor
="xlarge")
186 c9
= createDummyContainerObject("c9", flavor
="xlarge")
187 rm
.allocate(c6
) # calculate allocation
188 rm
.allocate(c7
) # calculate allocation
189 rm
.allocate(c8
) # calculate allocation
190 rm
.allocate(c9
) # calculate allocation
191 except NotEnoughResourcesAvailable
as e
:
192 self
.assertIn("Not enough compute", e
.message
)
194 self
.assertTrue(exception
)
196 def testAllocationMemLimit(self
):
198 Test MEM allocation limit
206 # create dummy resource model environment
207 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
208 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
209 reg
.register("test_dc", rm
)
211 # test over provisioning exeption
214 c6
= createDummyContainerObject("c6", flavor
="xlarge")
215 c7
= createDummyContainerObject("c7", flavor
="xlarge")
216 c8
= createDummyContainerObject("c8", flavor
="xlarge")
217 rm
.allocate(c6
) # calculate allocation
218 rm
.allocate(c7
) # calculate allocation
219 rm
.allocate(c8
) # calculate allocation
220 except NotEnoughResourcesAvailable
as e
:
221 self
.assertIn("Not enough memory", e
.message
)
223 self
.assertTrue(exception
)
227 Test the free procedure.
233 # create dummy resource model environment
234 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=1.0, dc_emulation_max_mem
=512)
235 rm
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
236 reg
.register("test_dc", rm
)
237 c1
= createDummyContainerObject("c6", flavor
="tiny")
238 rm
.allocate(c1
) # calculate allocation
239 self
.assertTrue(rm
.dc_alloc_cu
== 0.5)
241 self
.assertTrue(rm
.dc_alloc_cu
== 0)
243 @unittest.skipIf(os
.environ
.get("SON_EMU_IN_DOCKER") is not None,
244 "skipping test when running inside Docker container")
245 def testInRealTopo(self
):
247 Start a real container and check if limitations are really passed down to Conteinernet.
251 self
.createNet(nswitches
=0, ndatacenter
=1, nhosts
=2, ndockers
=0)
253 self
.net
.addLink(self
.dc
[0], self
.h
[0])
254 self
.net
.addLink(self
.h
[1], self
.dc
[0])
256 r
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
257 self
.dc
[0].assignResourceModel(r
)
258 # start Mininet network
260 # check number of running nodes
261 self
.assertTrue(len(self
.getContainernetContainers()) == 0)
262 self
.assertTrue(len(self
.net
.hosts
) == 2)
263 self
.assertTrue(len(self
.net
.switches
) == 1)
264 # check resource model and resource model registrar
265 self
.assertTrue(self
.dc
[0]._resource
_model
is not None)
266 self
.assertTrue(len(self
.net
.rm_registrar
.resource_models
) == 1)
268 # check if alloc was called during startCompute
269 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
270 tc1
= self
.dc
[0].startCompute("tc1", flavor_name
="tiny")
272 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 1)
274 # check if there is a real limitation set for containers cgroup
275 # deactivated for now, seems not to work in docker-in-docker setup used in CI
276 self
.assertEqual(float(tc1
.cpu_quota
)/tc1
.cpu_period
, 0.005)
278 # check if free was called during stopCompute
279 self
.dc
[0].stopCompute("tc1")
280 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
281 # check connectivity by using ping
282 self
.assertTrue(self
.net
.ping([self
.h
[0], self
.h
[1]]) <= 0.0)
283 # stop Mininet network
287 class testUpbOverprovisioningCloudDcRM(SimpleTestTopology
):
289 Test the UpbOverprovisioningCloudDc resource model.
292 def testAllocationComputations(self
):
294 Test the allocation procedures and correct calculations.
302 # create dummy resource model environment
303 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
304 rm
= UpbOverprovisioningCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
305 reg
.register("test_dc", rm
)
307 c1
= createDummyContainerObject("c1", flavor
="small")
308 rm
.allocate(c1
) # calculate allocation
309 self
.assertAlmostEqual(float(c1
.cpu_quota
) / c1
.cpu_period
, E_CPU
/ MAX_CU
* 1.0, places
=5)
310 self
.assertAlmostEqual(float(c1
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 128)
311 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
313 c2
= createDummyContainerObject("c2", flavor
="small")
314 rm
.allocate(c2
) # calculate allocation
315 self
.assertAlmostEqual(float(c2
.cpu_quota
) / c2
.cpu_period
, E_CPU
/ MAX_CU
* 1.0, places
=5)
316 self
.assertAlmostEqual(float(c2
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 128)
317 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
319 c3
= createDummyContainerObject("c3", flavor
="small")
320 rm
.allocate(c3
) # calculate allocation
321 self
.assertAlmostEqual(float(c3
.cpu_quota
) / c3
.cpu_period
, E_CPU
/ MAX_CU
* 1.0, places
=5)
322 self
.assertAlmostEqual(float(c3
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 128)
323 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
325 # from this container onwards, we should go to over provisioning mode:
326 c4
= createDummyContainerObject("c4", flavor
="small")
327 rm
.allocate(c4
) # calculate allocation
328 self
.assertAlmostEqual(float(c4
.cpu_quota
) / c4
.cpu_period
, E_CPU
/ MAX_CU
* (float(3) / 4), places
=5)
329 self
.assertAlmostEqual(float(c4
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 128, places
=5)
330 self
.assertAlmostEqual(rm
.cpu_op_factor
, 0.75)
332 c5
= createDummyContainerObject("c5", flavor
="small")
333 rm
.allocate(c5
) # calculate allocation
334 self
.assertAlmostEqual(float(c5
.cpu_quota
) / c5
.cpu_period
, E_CPU
/ MAX_CU
* (float(3) / 5), places
=5)
335 self
.assertAlmostEqual(float(c5
.mem_limit
/1024/1024), float(E_MEM
) / MAX_MU
* 128)
336 self
.assertAlmostEqual(rm
.cpu_op_factor
, 0.6)
339 class testUpbDummyRM(SimpleTestTopology
):
341 Test the UpbDummyRM resource model.
344 def testAllocationComputations(self
):
346 Test the allocation procedures and correct calculations.
354 # create dummy resource model environment
355 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
356 rm
= UpbDummyRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
357 reg
.register("test_dc", rm
)
359 c1
= createDummyContainerObject("c1", flavor
="small")
360 rm
.allocate(c1
) # calculate allocation
361 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 1)
363 c2
= createDummyContainerObject("c2", flavor
="small")
364 rm
.allocate(c2
) # calculate allocation
365 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 2)