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):
99 # take defaukt values from son-emu
100 self
.resources
= dict(
106 #self.cpu_period = self.resources['cpu_period']
107 #self.cpu_quota = self.resources['cpu_quota']
108 #self.mem_limit = self.resources['mem_limit']
109 #self.memswap_limit = self.resources['memswap_limit']
111 def updateCpuLimit(self
, cpu_period
, cpu_quota
):
112 self
.resources
['cpu_period'] = cpu_period
113 self
.resources
['cpu_quota'] = cpu_quota
115 def updateMemoryLimit(self
, mem_limit
):
116 self
.resources
['mem_limit'] = mem_limit
120 d
.flavor_name
= flavor
126 class testUpbSimpleCloudDcRM(SimpleTestTopology
):
128 Test the UpbSimpleCloudDc resource model.
131 def testAllocationComputations(self
):
133 Test the allocation procedures and correct calculations.
141 # create dummy resource model environment
142 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
143 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
144 reg
.register("test_dc", rm
)
146 c1
= createDummyContainerObject("c1", flavor
="tiny")
147 rm
.allocate(c1
) # calculate allocation
148 self
.assertEqual(float(c1
.resources
['cpu_quota']) / c1
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 0.5) # validate compute result
149 self
.assertEqual(float(c1
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 32) # validate memory result
151 c2
= createDummyContainerObject("c2", flavor
="small")
152 rm
.allocate(c2
) # calculate allocation
153 self
.assertEqual(float(c2
.resources
['cpu_quota']) / c2
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1) # validate compute result
154 self
.assertEqual(float(c2
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 128) # validate memory result
156 c3
= createDummyContainerObject("c3", flavor
="medium")
157 rm
.allocate(c3
) # calculate allocation
158 self
.assertEqual(float(c3
.resources
['cpu_quota']) / c3
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 4) # validate compute result
159 self
.assertEqual(float(c3
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 256) # validate memory result
161 c4
= createDummyContainerObject("c4", flavor
="large")
162 rm
.allocate(c4
) # calculate allocation
163 self
.assertEqual(float(c4
.resources
['cpu_quota']) / c4
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 8) # validate compute result
164 self
.assertEqual(float(c4
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 512) # validate memory result
166 c5
= createDummyContainerObject("c5", flavor
="xlarge")
167 rm
.allocate(c5
) # calculate allocation
168 self
.assertEqual(float(c5
.resources
['cpu_quota']) / c5
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 16) # validate compute result
169 self
.assertEqual(float(c5
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 1024) # validate memory result
172 def testAllocationCpuLimit(self
):
174 Test CPU allocation limit
182 # create dummy resource model environment
183 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
184 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
185 reg
.register("test_dc", rm
)
187 # test over provisioning exeption
190 c6
= createDummyContainerObject("c6", flavor
="xlarge")
191 c7
= createDummyContainerObject("c7", flavor
="xlarge")
192 c8
= createDummyContainerObject("c8", flavor
="xlarge")
193 c9
= createDummyContainerObject("c9", flavor
="xlarge")
194 rm
.allocate(c6
) # calculate allocation
195 rm
.allocate(c7
) # calculate allocation
196 rm
.allocate(c8
) # calculate allocation
197 rm
.allocate(c9
) # calculate allocation
198 except NotEnoughResourcesAvailable
as e
:
199 self
.assertIn("Not enough compute", e
.message
)
201 self
.assertTrue(exception
)
203 def testAllocationMemLimit(self
):
205 Test MEM allocation limit
213 # create dummy resource model environment
214 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
215 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
216 reg
.register("test_dc", rm
)
218 # test over provisioning exeption
221 c6
= createDummyContainerObject("c6", flavor
="xlarge")
222 c7
= createDummyContainerObject("c7", flavor
="xlarge")
223 c8
= createDummyContainerObject("c8", flavor
="xlarge")
224 rm
.allocate(c6
) # calculate allocation
225 rm
.allocate(c7
) # calculate allocation
226 rm
.allocate(c8
) # calculate allocation
227 except NotEnoughResourcesAvailable
as e
:
228 self
.assertIn("Not enough memory", e
.message
)
230 self
.assertTrue(exception
)
234 Test the free procedure.
240 # create dummy resource model environment
241 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=1.0, dc_emulation_max_mem
=512)
242 rm
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
243 reg
.register("test_dc", rm
)
244 c1
= createDummyContainerObject("c6", flavor
="tiny")
245 rm
.allocate(c1
) # calculate allocation
246 self
.assertTrue(rm
.dc_alloc_cu
== 0.5)
248 self
.assertTrue(rm
.dc_alloc_cu
== 0)
250 @unittest.skipIf(os
.environ
.get("SON_EMU_IN_DOCKER") is not None,
251 "skipping test when running inside Docker container")
252 def testInRealTopo(self
):
254 Start a real container and check if limitations are really passed down to Conteinernet.
258 self
.createNet(nswitches
=0, ndatacenter
=1, nhosts
=2, ndockers
=0)
260 self
.net
.addLink(self
.dc
[0], self
.h
[0])
261 self
.net
.addLink(self
.h
[1], self
.dc
[0])
263 r
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
264 self
.dc
[0].assignResourceModel(r
)
265 # start Mininet network
267 # check number of running nodes
268 self
.assertTrue(len(self
.getContainernetContainers()) == 0)
269 self
.assertTrue(len(self
.net
.hosts
) == 2)
270 self
.assertTrue(len(self
.net
.switches
) == 1)
271 # check resource model and resource model registrar
272 self
.assertTrue(self
.dc
[0]._resource
_model
is not None)
273 self
.assertTrue(len(self
.net
.rm_registrar
.resource_models
) == 1)
275 # check if alloc was called during startCompute
276 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
277 tc1
= self
.dc
[0].startCompute("tc1", flavor_name
="tiny")
279 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 1)
281 # check if there is a real limitation set for containers cgroup
282 # deactivated for now, seems not to work in docker-in-docker setup used in CI
283 self
.assertEqual(float(tc1
.resources
['cpu_quota'])/tc1
.resources
['cpu_period'], 0.005)
285 # check if free was called during stopCompute
286 self
.dc
[0].stopCompute("tc1")
287 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
288 # check connectivity by using ping
289 self
.assertTrue(self
.net
.ping([self
.h
[0], self
.h
[1]]) <= 0.0)
290 # stop Mininet network
294 class testUpbOverprovisioningCloudDcRM(SimpleTestTopology
):
296 Test the UpbOverprovisioningCloudDc resource model.
299 def testAllocationComputations(self
):
301 Test the allocation procedures and correct calculations.
309 # create dummy resource model environment
310 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
311 rm
= UpbOverprovisioningCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
312 reg
.register("test_dc", rm
)
314 c1
= createDummyContainerObject("c1", flavor
="small")
315 rm
.allocate(c1
) # calculate allocation
316 self
.assertAlmostEqual(float(c1
.resources
['cpu_quota']) / c1
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1.0, places
=5)
317 self
.assertAlmostEqual(float(c1
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 128)
318 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
320 c2
= createDummyContainerObject("c2", flavor
="small")
321 rm
.allocate(c2
) # calculate allocation
322 self
.assertAlmostEqual(float(c2
.resources
['cpu_quota']) / c2
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1.0, places
=5)
323 self
.assertAlmostEqual(float(c2
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 128)
324 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
326 c3
= createDummyContainerObject("c3", flavor
="small")
327 rm
.allocate(c3
) # calculate allocation
328 self
.assertAlmostEqual(float(c3
.resources
['cpu_quota']) / c3
.resources
['cpu_period'], E_CPU
/ MAX_CU
* 1.0, places
=5)
329 self
.assertAlmostEqual(float(c3
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 128)
330 self
.assertAlmostEqual(rm
.cpu_op_factor
, 1.0)
332 # from this container onwards, we should go to over provisioning mode:
333 c4
= createDummyContainerObject("c4", flavor
="small")
334 rm
.allocate(c4
) # calculate allocation
335 self
.assertAlmostEqual(float(c4
.resources
['cpu_quota']) / c4
.resources
['cpu_period'], E_CPU
/ MAX_CU
* (float(3) / 4), places
=5)
336 self
.assertAlmostEqual(float(c4
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 128, places
=5)
337 self
.assertAlmostEqual(rm
.cpu_op_factor
, 0.75)
339 c5
= createDummyContainerObject("c5", flavor
="small")
340 rm
.allocate(c5
) # calculate allocation
341 self
.assertAlmostEqual(float(c5
.resources
['cpu_quota']) / c5
.resources
['cpu_period'], E_CPU
/ MAX_CU
* (float(3) / 5), places
=5)
342 self
.assertAlmostEqual(float(c5
.resources
['mem_limit']/1024/1024), float(E_MEM
) / MAX_MU
* 128)
343 self
.assertAlmostEqual(rm
.cpu_op_factor
, 0.6)
346 class testUpbDummyRM(SimpleTestTopology
):
348 Test the UpbDummyRM resource model.
351 def testAllocationComputations(self
):
353 Test the allocation procedures and correct calculations.
361 # create dummy resource model environment
362 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
363 rm
= UpbDummyRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
364 reg
.register("test_dc", rm
)
366 c1
= createDummyContainerObject("c1", flavor
="small")
367 rm
.allocate(c1
) # calculate allocation
368 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 1)
370 c2
= createDummyContainerObject("c2", flavor
="small")
371 rm
.allocate(c2
) # calculate allocation
372 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 2)