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.cpu_period = -1
102 # self.mem_limit = -1
103 # self.memswap_limit = -1
105 def updateCpuLimit(self
, cpu_period
, cpu_quota
):
106 self
.cpu_period
= cpu_period
107 self
.cpu_quota
= cpu_quota
109 def updateMemoryLimit(self
, mem_limit
):
110 self
.mem_limit
= mem_limit
114 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(dc_emulation_max_cpu
=E_CPU
, dc_emulation_max_mem
=E_MEM
)
137 rm
= UpbSimpleCloudDcRM(max_cu
=MAX_CU
, max_mu
=MAX_MU
)
138 reg
.register("test_dc", rm
)
140 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
145 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
150 c3
= createDummyContainerObject("c3", flavor
="medium")
151 rm
.allocate(c3
) # calculate allocation
152 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
155 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
160 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
166 def testAllocationCpuLimit(self
):
168 Test CPU allocation limit
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
)
181 # test over provisioning exeption
184 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
192 except NotEnoughResourcesAvailable
as e
:
193 self
.assertIn("Not enough compute", e
.message
)
195 self
.assertTrue(exception
)
197 def testAllocationMemLimit(self
):
199 Test MEM allocation limit
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
)
212 # test over provisioning exeption
215 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
221 except NotEnoughResourcesAvailable
as e
:
222 self
.assertIn("Not enough memory", e
.message
)
224 self
.assertTrue(exception
)
228 Test the free procedure.
234 # create dummy resource model environment
235 reg
= ResourceModelRegistrar(dc_emulation_max_cpu
=1.0, dc_emulation_max_mem
=512)
236 rm
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
237 reg
.register("test_dc", rm
)
238 c1
= createDummyContainerObject("c6", flavor
="tiny")
239 rm
.allocate(c1
) # calculate allocation
240 self
.assertTrue(rm
.dc_alloc_cu
== 0.5)
242 self
.assertTrue(rm
.dc_alloc_cu
== 0)
244 @unittest.skipIf(os
.environ
.get("SON_EMU_IN_DOCKER") is not None,
245 "skipping test when running inside Docker container")
246 def testInRealTopo(self
):
248 Start a real container and check if limitations are really passed down to Conteinernet.
252 self
.createNet(nswitches
=0, ndatacenter
=1, nhosts
=2, ndockers
=0)
254 self
.net
.addLink(self
.dc
[0], self
.h
[0])
255 self
.net
.addLink(self
.h
[1], self
.dc
[0])
257 r
= UpbSimpleCloudDcRM(max_cu
=100, max_mu
=100)
258 self
.dc
[0].assignResourceModel(r
)
259 # start Mininet network
261 # check number of running nodes
262 self
.assertTrue(len(self
.getContainernetContainers()) == 0)
263 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)
269 # check if alloc was called during startCompute
270 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
271 tc1
= self
.dc
[0].startCompute("tc1", flavor_name
="tiny")
273 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 1)
275 # check if there is a real limitation set for containers cgroup
276 # deactivated for now, seems not to work in docker-in-docker setup used in CI
277 self
.assertEqual(float(tc1
.cpu_quota
)/tc1
.cpu_period
, 0.005)
279 # check if free was called during stopCompute
280 self
.dc
[0].stopCompute("tc1")
281 self
.assertTrue(len(r
._allocated
_compute
_instances
) == 0)
282 # check connectivity by using ping
283 self
.assertTrue(self
.net
.ping([self
.h
[0], self
.h
[1]]) <= 0.0)
284 # stop Mininet network
288 class testUpbOverprovisioningCloudDcRM(SimpleTestTopology
):
290 Test the UpbOverprovisioningCloudDc resource model.
293 def testAllocationComputations(self
):
295 Test the allocation procedures and correct calculations.
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
)
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)
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)
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)
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)
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)
340 class testUpbDummyRM(SimpleTestTopology
):
342 Test the UpbDummyRM resource model.
345 def testAllocationComputations(self
):
347 Test the allocation procedures and correct calculations.
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
)
360 c1
= createDummyContainerObject("c1", flavor
="small")
361 rm
.allocate(c1
) # calculate allocation
362 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 1)
364 c2
= createDummyContainerObject("c2", flavor
="small")
365 rm
.allocate(c2
) # calculate allocation
366 self
.assertEqual(len(rm
._allocated
_compute
_instances
), 2)