Improved test to be skipped when executed within a container.
[osm/vim-emu.git] / src / emuvim / test / test_resourcemodel_api.py
1 import time
2 import os
3 from emuvim.test.base import SimpleTestTopology
4 from emuvim.dcemulator.resourcemodel import BaseResourceModel, ResourceFlavor
5 from emuvim.dcemulator.resourcemodel.upb.simple import UpbSimpleCloudDcRM
6 from emuvim.dcemulator.resourcemodel import ResourceModelRegistrar
7
8
9 class testResourceModel(SimpleTestTopology):
10 """
11 Test the general resource model API and functionality.
12 """
13
14 def testBaseResourceModelApi(self):
15 """
16 Tast bare API without real resource madel.
17 :return:
18 """
19 r = BaseResourceModel()
20 # check if default flavors are there
21 self.assertTrue(len(r._flavors) == 5)
22 # check addFlavor functionality
23 f = ResourceFlavor("test", {"testmetric": 42})
24 r.addFlavour(f)
25 self.assertTrue("test" in r._flavors)
26 self.assertTrue(r._flavors.get("test").get("testmetric") == 42)
27
28 def testAddRmToDc(self):
29 """
30 Test is allocate/free is called when a RM is added to a DC.
31 :return:
32 """
33 # create network
34 self.createNet(nswitches=0, ndatacenter=1, nhosts=2, ndockers=0)
35 # setup links
36 self.net.addLink(self.dc[0], self.h[0])
37 self.net.addLink(self.h[1], self.dc[0])
38 # add resource model
39 r = BaseResourceModel()
40 self.dc[0].assignResourceModel(r)
41 # start Mininet network
42 self.startNet()
43 # check number of running nodes
44 self.assertTrue(len(self.getDockernetContainers()) == 0)
45 self.assertTrue(len(self.net.hosts) == 2)
46 self.assertTrue(len(self.net.switches) == 1)
47 # check resource model and resource model registrar
48 self.assertTrue(self.dc[0]._resource_model is not None)
49 self.assertTrue(len(self.net.rm_registrar.resource_models) == 1)
50
51 # check if alloc was called during startCompute
52 self.assertTrue(len(r._allocated_compute_instances) == 0)
53 self.dc[0].startCompute("tc1")
54 time.sleep(1)
55 self.assertTrue(len(r._allocated_compute_instances) == 1)
56 # check if free was called during stopCompute
57 self.dc[0].stopCompute("tc1")
58 self.assertTrue(len(r._allocated_compute_instances) == 0)
59 # check connectivity by using ping
60 self.assertTrue(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
61 # stop Mininet network
62 self.stopNet()
63
64
65 def createDummyContainerObject(name, flavor):
66
67 class DummyContainer(object):
68
69 def __init__(self):
70 self.cpu_period = -1
71 self.cpu_quota = -1
72 self.mem_limit = -1
73 self.memswap_limit = -1
74
75 def updateCpuLimit(self, cpu_period, cpu_quota):
76 self.cpu_period = cpu_period
77 self.cpu_quota = cpu_quota
78
79 def updateMemoryLimit(self, mem_limit):
80 self.mem_limit = mem_limit
81
82 d = DummyContainer()
83 d.name = name
84 d.flavor_name = flavor
85 return d
86
87
88
89
90 class testUpbSimpleCloudDcRM(SimpleTestTopology):
91 """
92 Test the UpbSimpleCloudDc resource model.
93 """
94
95 def testAllocation(self):
96 """
97 Test the allocation procedures and correct calculations.
98 :return:
99 """
100 # config
101 E_CPU = 1.0
102 MAX_CU = 100
103 E_MEM = 512
104 MAX_MU = 2048
105 # create dummy resource model environment
106 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
107 rm = UpbSimpleCloudDcRM(max_cu=MAX_CU, max_mu=MAX_MU)
108 reg.register("test_dc", rm)
109
110 c1 = createDummyContainerObject("c1", flavor="tiny")
111 rm.allocate(c1) # calculate allocation
112 self.assertEqual(float(c1.cpu_quota) / c1.cpu_period, E_CPU / MAX_CU * 0.5) # validate compute result
113 self.assertEqual(float(c1.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 32) # validate memory result
114
115 c2 = createDummyContainerObject("c2", flavor="small")
116 rm.allocate(c2) # calculate allocation
117 self.assertEqual(float(c2.cpu_quota) / c2.cpu_period, E_CPU / MAX_CU * 1) # validate compute result
118 self.assertEqual(float(c2.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 128) # validate memory result
119
120
121 c3 = createDummyContainerObject("c3", flavor="medium")
122 res = rm.allocate(c3) # calculate allocation
123 self.assertEqual(float(c3.cpu_quota) / c3.cpu_period, E_CPU / MAX_CU * 4) # validate compute result
124 self.assertEqual(float(c3.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 256) # validate memory result
125
126
127 c4 = createDummyContainerObject("c4", flavor="large")
128 rm.allocate(c4) # calculate allocation
129 self.assertEqual(float(c4.cpu_quota) / c4.cpu_period, E_CPU / MAX_CU * 8) # validate compute result
130 self.assertEqual(float(c4.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 512) # validate memory result
131
132
133 c5 = createDummyContainerObject("c5", flavor="xlarge")
134 rm.allocate(c5) # calculate allocation
135 self.assertEqual(float(c5.cpu_quota) / c5.cpu_period, E_CPU / MAX_CU * 16) # validate compute result
136 self.assertEqual(float(c5.mem_limit/1024/1024), float(E_MEM) / MAX_MU * 1024) # validate memory result
137
138
139 def testAllocationCpuLimit(self):
140 """
141 Test CPU allocation limit
142 :return:
143 """
144 # config
145 E_CPU = 1.0
146 MAX_CU = 40
147 E_MEM = 512
148 MAX_MU = 4096
149 # create dummy resource model environment
150 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
151 rm = UpbSimpleCloudDcRM(max_cu=MAX_CU, max_mu=MAX_MU)
152 reg.register("test_dc", rm)
153
154 # test over provisioning exeption
155 exception = False
156 try:
157 c6 = createDummyContainerObject("c6", flavor="xlarge")
158 c7 = createDummyContainerObject("c7", flavor="xlarge")
159 c8 = createDummyContainerObject("c8", flavor="xlarge")
160 c9 = createDummyContainerObject("c9", flavor="xlarge")
161 rm.allocate(c6) # calculate allocation
162 rm.allocate(c7) # calculate allocation
163 rm.allocate(c8) # calculate allocation
164 rm.allocate(c9) # calculate allocation
165 except Exception as e:
166 self.assertIn("Not enough compute", e.message)
167 exception = True
168 self.assertTrue(exception)
169
170 def testAllocationMemLimit(self):
171 """
172 Test MEM allocation limit
173 :return:
174 """
175 # config
176 E_CPU = 1.0
177 MAX_CU = 500
178 E_MEM = 512
179 MAX_MU = 2048
180 # create dummy resource model environment
181 reg = ResourceModelRegistrar(dc_emulation_max_cpu=E_CPU, dc_emulation_max_mem=E_MEM)
182 rm = UpbSimpleCloudDcRM(max_cu=MAX_CU, max_mu=MAX_MU)
183 reg.register("test_dc", rm)
184
185 # test over provisioning exeption
186 exception = False
187 try:
188 c6 = createDummyContainerObject("c6", flavor="xlarge")
189 c7 = createDummyContainerObject("c7", flavor="xlarge")
190 c8 = createDummyContainerObject("c8", flavor="xlarge")
191 rm.allocate(c6) # calculate allocation
192 rm.allocate(c7) # calculate allocation
193 rm.allocate(c8) # calculate allocation
194 except Exception as e:
195 self.assertIn("Not enough memory", e.message)
196 exception = True
197 self.assertTrue(exception)
198
199 def testFree(self):
200 """
201 Test the free procedure.
202 :return:
203 """
204 # config
205 E_CPU = 1.0
206 MAX_CU = 100
207 # create dummy resource model environment
208 reg = ResourceModelRegistrar(dc_emulation_max_cpu=1.0, dc_emulation_max_mem=512)
209 rm = UpbSimpleCloudDcRM(max_cu=100, max_mu=100)
210 reg.register("test_dc", rm)
211 c1 = createDummyContainerObject("c6", flavor="tiny")
212 rm.allocate(c1) # calculate allocation
213 self.assertTrue(rm.dc_alloc_cu == 0.5)
214 rm.free(c1)
215 self.assertTrue(rm.dc_alloc_cu == 0)
216
217 def testInRealTopo(self):
218 """
219 Start a real container and check if limitations are really passed down to Dockernet.
220 :return:
221 """
222 # ATTENTION: This test should only be executed if emu runs not inside a Docker container,
223 # because it manipulates cgroups.
224 if os.environ.get("SON_EMU_IN_DOCKER") is not None:
225 return
226 # create network
227 self.createNet(nswitches=0, ndatacenter=1, nhosts=2, ndockers=0)
228 # setup links
229 self.net.addLink(self.dc[0], self.h[0])
230 self.net.addLink(self.h[1], self.dc[0])
231 # add resource model
232 r = UpbSimpleCloudDcRM(max_cu=100, max_mu=100)
233 self.dc[0].assignResourceModel(r)
234 # start Mininet network
235 self.startNet()
236 # check number of running nodes
237 self.assertTrue(len(self.getDockernetContainers()) == 0)
238 self.assertTrue(len(self.net.hosts) == 2)
239 self.assertTrue(len(self.net.switches) == 1)
240 # check resource model and resource model registrar
241 self.assertTrue(self.dc[0]._resource_model is not None)
242 self.assertTrue(len(self.net.rm_registrar.resource_models) == 1)
243
244 # check if alloc was called during startCompute
245 self.assertTrue(len(r._allocated_compute_instances) == 0)
246 tc1 = self.dc[0].startCompute("tc1", flavor_name="tiny")
247 time.sleep(1)
248 self.assertTrue(len(r._allocated_compute_instances) == 1)
249
250 # check if there is a real limitation set for containers cgroup
251 # deactivated for now, seems not to work in docker-in-docker setup used in CI
252 self.assertEqual(float(tc1.cpu_quota)/tc1.cpu_period, 0.005)
253
254 # check if free was called during stopCompute
255 self.dc[0].stopCompute("tc1")
256 self.assertTrue(len(r._allocated_compute_instances) == 0)
257 # check connectivity by using ping
258 self.assertTrue(self.net.ping([self.h[0], self.h[1]]) <= 0.0)
259 # stop Mininet network
260 self.stopNet()
261
262
263