Skip to content

The class "vMicroservice" is designed to resemble a deployment in Kubernetes, comprising one or more instances of the "vContainer" class. It encompasses the following important member functions and behaviours:

  1. Recovery of Failed vContainers: When any "vContainer" crashes or encounters a failure, the "vMicroservice" includes a member function that facilitates the recovery of these failed containers. This recovery process is initiated immediately after a container failure or after a specific delay, as determined by the simulation.
  2. Horizontal Scaling: The "vMicroservice" is responsible for horizontal scaling, which involves dynamically adjusting the number of "vContainer" instances based on certain conditions. If the overall CPU/RAM usage of all current "vContainer" instances exceeds a predetermined threshold, a new "vContainer" will be created to handle the increased workload. Conversely, if a "vContainer" is identified as being under-utilized, it may be forcibly terminated. Horizontal scaling is implemented as an event, and only one horizontal scaling event can occur per "vMicroservice" instance at any given time during the simulation.
  3. Readiness of vMicroservice: The readiness of a "vMicroservice" is determined by the number of current "vContainer" instances reaching the minimum required number. This minimum requirement ensures that the "vMicroservice" is considered ready for operation.

In summary, the "vMicroservice" class emulates the behaviour of deployments in Kubernetes, facilitating the management of "vContainer" instances, recovery from failures, horizontal scaling, and readiness evaluation within the simulated cloud environment.

Bases: vSoftwareEntity, ABC

Source code in PyCloudSim\entity\v_microservice.py
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
class vMicroservice(vSoftwareEntity, ABC):
    def __init__(
        self,
        cpu: int | Callable[..., int],
        ram: int | Callable[..., int],
        image_size: int | Callable[..., int],
        cpu_limit: int | Callable[..., int] | None = None,
        ram_limit: int | Callable[..., int] | None = None,
        volumes: List[Tuple[int, str, str]] = [],
        priority: int | Callable[..., int] = 0,
        deamon: bool | Callable[..., bool] = False,
        min_num_instances: int | Callable[..., int] = 1,
        max_num_instances: int | Callable[..., int] = 3,
        loadbalancer: vLoadbalancer = Bestfit(),
        label: str | None = None,
        create_at: int
        | float
        | Callable[..., int]
        | Callable[..., float]
        | None = None,
        terminate_at: int
        | float
        | Callable[..., int]
        | Callable[..., float]
        | None = None,
        precursor: Entity | List[Entity] | None = None,
    ) -> None:
        """Base for simulated microservices. It includes the horizontal scaling functionality."""
        super().__init__(label, create_at, terminate_at, precursor)

        self._cpu = cpu
        self._ram = ram
        self._image_size = image_size
        self._cpu_limit = cpu_limit
        self._ram_limit = ram_limit
        self._volume_descriptions = volumes
        self._priority = priority
        self._demmon = deamon
        self._scaling = False

        if callable(min_num_instances):
            self._min_num_instances = round(min_num_instances())
        else:
            self._min_num_instances = min_num_instances

        if callable(max_num_instances):
            self._max_num_instances = round(max_num_instances())
        else:
            self._max_num_instances = max_num_instances

        self._containers: List[vContainer] = EntityList(label=f"{self} Containers")

        self._loadbalancer = loadbalancer

        for _ in range(self._min_num_instances):
            self.containers.append(
                vContainer(
                    self.cpu,
                    self.ram,
                    self.image_size,
                    self.cpu_limit,
                    self.ram_limit,
                    self.volume_descriptions,
                    self.priority,
                    self.deamon,
                    label=f"{self.label}-{len(self._containers)}",
                )
            )

    def horizontal_scale_up(self, num_instances: int, at: int | float):
        """Horizontal scale up the microservice by adding new container instances."""

        if self.scaling:
            return

        self._scaling = True

        @self.instant_event(at, label=f"{self} Horizontal Scale Up", priority=-1)
        def _scale_up():
            for _ in range(num_instances):
                self.containers.append(
                    vContainer(
                        self.cpu,
                        self.ram,
                        self.image_size,
                        self.cpu_limit,
                        self.ram_limit,
                        self.volume_descriptions,
                        self.priority,
                        self.deamon,
                        label=f"{self.label}-{len(self._containers)}",
                        create_at=simulation.now,
                    )
                )
            self._scaling = False

    def horizontal_scale_down(self, num_instances: int, at: int | float):
        """Horizontal scale down the microservice by terminating container instances. This can not cause the number of container instances to be less than the minimum number of instances."""
        if self.scaling:
            return

        self._scaling = True

        @self.instant_event(at, label=f"{self} Horizontal Scale Down", priority=-1)
        def _scale_down():
            for i in range(
                min([num_instances, len(self.containers) - self.min_num_instances])
            ):
                self.containers[i].terminate(simulation.now)

    def vertical_scale(
        self,
        at: int | float,
        cpu: int | Callable[..., int],
        ram: int | Callable[..., int],
        image_size: int | Callable[..., int],
        cpu_limit: int | Callable[..., int] | None = None,
        ram_limit: int | Callable[..., int] | None = None,
        init_delay: int | float | Callable[..., int] | Callable[..., float] = 0,
        priority: int | Callable[..., int] = 0,
        deamon: bool | Callable[..., bool] = False,
        min_num_instances: int | Callable[..., int] = 1,
        max_num_instances: int | Callable[..., int] = 3,
        evaluation_interval: int
        | float
        | Callable[..., int]
        | Callable[..., float] = 0.1,
        cpu_upper_threshold: float | Callable[..., float] = 0.8,
        cpu_lower_threshold: float | Callable[..., float] = 0.2,
        ram_upper_threshold: float | Callable[..., float] = 0.8,
        ram_lower_threshold: float | Callable[..., float] = 0.2,
    ):
        """Scaling the microservice vertically by changing the attributes of the microservice. This will terminate all the current container instances and create new container instances with the new attributes."""

        @self.instant_event(at, label=f"{self} Vertical Scale", priority=-1)
        def _vertical_scale():
            # update the attributes
            self._cpu = cpu
            self._ram = ram
            self._image_size = image_size
            self._cpu_limit = cpu_limit
            self._ram_limit = ram_limit
            self._priority = priority
            self._demmon = deamon
            self._scaling = False

            if callable(min_num_instances):
                self._min_num_instances = round(min_num_instances())
            else:
                self._min_num_instances = min_num_instances

            if callable(max_num_instances):
                self._max_num_instances = round(max_num_instances())
            else:
                self._max_num_instances = max_num_instances

            # record the current number of instances
            number_instance = len(self.containers)
            # terminate all the current instances
            for container in self.containers:
                container.terminate(simulation.now)
            # create new instances
            for _ in range(number_instance):
                self.containers.append(
                    vContainer(
                        self.cpu,
                        self.ram,
                        self.image_size,
                        self.cpu_limit,
                        self.ram_limit,
                        self.volume_descriptions,
                        self.priority,
                        self.deamon,
                        label=f"{self.label}-{len(self._containers)}",
                        create_at=simulation.now,
                    )
                )

    @abstractmethod
    def horizontal_scale_up_triggered(self) -> bool:
        """Abstract method for evaluating if the microservice should be scaled up horizontally."""
        pass

    @abstractmethod
    def horizontal_scale_down_triggered(self) -> bool:
        """Abstract method for evaluating if the microservice should be scaled down horizontally."""
        pass

    def getContainer(self):
        """Get the container instance according to the loadbalancer."""
        return self.loadbalancer.getContainer(self)

    def on_creation(self):
        """Creation procedure of the microservice. It will create the container instances and the evaluator."""
        for container in self._containers:
            container.create(simulation.now)

        @self.continuous_event(
            at=simulation.now,
            interval=simulation.min_time_unit,
            duration=inf,
            label=f"{self} Evaluator",
        )
        def _evaluator():
            initiated_containers = [
                container for container in self._containers if container.initiated
            ]
            # check if the microservice is ready
            if len(initiated_containers) < self.min_num_instances:
                if self.ready:
                    self.state.remove(Constants.READY)
                    for _ in range(self.min_num_instances - len(initiated_containers)):
                        self.containers.append(
                            vContainer(
                                self.cpu,
                                self.ram,
                                self.image_size,
                                self.cpu_limit,
                                self.ram_limit,
                                self.volume_descriptions,
                                self.priority,
                                self.deamon,
                                label=f"{self.label}-{len(self._containers)}",
                                create_at=simulation.now,
                            )
                        )
                    logger.info(f"{simulation.now}:\t{self} is not ready, recreating {self.min_num_instances - len(initiated_containers)} container instances")
                return
            else:
                if not self.ready:
                    self.state.append(Constants.READY)
                    logger.info(f"{simulation.now}:\t{self} is ready")

            # check if any container instance is pending:
            if len(initiated_containers) != len(self.containers):
                # if any instance is pending, skip the scaling evaluation
                return

            # check if the microservice should be scaled up
            if len(self.containers) < self.max_num_instances:
                if self.horizontal_scale_up_triggered():
                    self.horizontal_scale_up(1, simulation.now)
                    return

            # check if the microservice should be scaled down
            if len(self.containers) > self.min_num_instances:
                if self.horizontal_scale_down_triggered():
                    self.horizontal_scale_down(1, simulation.now)
                    return

    def on_termination(self):
        for container in self._containers:
            container.terminate(simulation.now)

    @property
    def cpu(self):
        """Return the required CPU time for each container instance."""
        return self._cpu

    @property
    def ram(self):
        """Return the required RAM for each container instance."""
        return self._ram

    @property
    def image_size(self):
        """Return the image size for each container instance."""
        return self._image_size

    @property
    def cpu_limit(self):
        """Return the CPU limit for each container instance."""
        return self._cpu_limit

    @property
    def ram_limit(self):
        """Return the RAM limit for each container instance."""
        return self._ram_limit

    @property
    def priority(self):
        """Return the priority for each container instance."""
        return self._priority

    @property
    def deamon(self):
        """Return the deamon flag for each container instance."""
        return self._demmon

    @property
    def min_num_instances(self):
        """Return the minimum number of container instances."""
        return self._min_num_instances

    @property
    def max_num_instances(self):
        """Return the maximum number of container instances."""
        return self._max_num_instances

    @property
    def containers(self):
        """Return the list of container instances."""
        return self._containers

    @property
    def cpu_usage(self):
        """Return the overall CPU usage of the microservice."""
        return sum(
            container.cpu_usage for container in self._containers if container.initiated
        )

    @property
    def cpu_utilization(self):
        """Return the overall CPU utilization of the microservice."""
        return sum(
            container.cpu_utilization
            for container in self._containers
            if container.initiated
        ) / len(self.containers)

    @property
    def ram_usage(self):
        """Return the overall RAM usage of the microservice."""
        return sum(
            container.ram_usage for container in self._containers if container.initiated
        )

    @property
    def ram_utilization(self):
        """Return the overall RAM utilization of the microservice."""
        return sum(
            container.ram_utilization
            for container in self._containers
            if container.initiated
        ) / len(self.containers)

    @property
    def num_active_containers(self):
        """Return the number of container instances."""
        active_containers = [container for container in self.containers if container.initiated]
        return len(active_containers)

    @property
    def scaling(self):
        """Return true if the microservice is scaling up or down."""
        return self._scaling

    @property
    def ready(self):
        """Return true if the microservice is ready."""
        return Constants.READY in self.state

    @property
    def loadbalancer(self):
        """Return the loadbalancer of the microservice."""
        return self._loadbalancer

    @property
    def volume_descriptions(self):
        """Return the volume descriptions of the microservice."""
        return self._volume_descriptions

containers property

Return the list of container instances.

cpu property

Return the required CPU time for each container instance.

cpu_limit property

Return the CPU limit for each container instance.

cpu_usage property

Return the overall CPU usage of the microservice.

cpu_utilization property

Return the overall CPU utilization of the microservice.

deamon property

Return the deamon flag for each container instance.

image_size property

Return the image size for each container instance.

loadbalancer property

Return the loadbalancer of the microservice.

max_num_instances property

Return the maximum number of container instances.

min_num_instances property

Return the minimum number of container instances.

num_active_containers property

Return the number of container instances.

priority property

Return the priority for each container instance.

ram property

Return the required RAM for each container instance.

ram_limit property

Return the RAM limit for each container instance.

ram_usage property

Return the overall RAM usage of the microservice.

ram_utilization property

Return the overall RAM utilization of the microservice.

ready property

Return true if the microservice is ready.

scaling property

Return true if the microservice is scaling up or down.

volume_descriptions property

Return the volume descriptions of the microservice.

__init__(cpu, ram, image_size, cpu_limit=None, ram_limit=None, volumes=[], priority=0, deamon=False, min_num_instances=1, max_num_instances=3, loadbalancer=Bestfit(), label=None, create_at=None, terminate_at=None, precursor=None)

Base for simulated microservices. It includes the horizontal scaling functionality.

Source code in PyCloudSim\entity\v_microservice.py
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def __init__(
    self,
    cpu: int | Callable[..., int],
    ram: int | Callable[..., int],
    image_size: int | Callable[..., int],
    cpu_limit: int | Callable[..., int] | None = None,
    ram_limit: int | Callable[..., int] | None = None,
    volumes: List[Tuple[int, str, str]] = [],
    priority: int | Callable[..., int] = 0,
    deamon: bool | Callable[..., bool] = False,
    min_num_instances: int | Callable[..., int] = 1,
    max_num_instances: int | Callable[..., int] = 3,
    loadbalancer: vLoadbalancer = Bestfit(),
    label: str | None = None,
    create_at: int
    | float
    | Callable[..., int]
    | Callable[..., float]
    | None = None,
    terminate_at: int
    | float
    | Callable[..., int]
    | Callable[..., float]
    | None = None,
    precursor: Entity | List[Entity] | None = None,
) -> None:
    """Base for simulated microservices. It includes the horizontal scaling functionality."""
    super().__init__(label, create_at, terminate_at, precursor)

    self._cpu = cpu
    self._ram = ram
    self._image_size = image_size
    self._cpu_limit = cpu_limit
    self._ram_limit = ram_limit
    self._volume_descriptions = volumes
    self._priority = priority
    self._demmon = deamon
    self._scaling = False

    if callable(min_num_instances):
        self._min_num_instances = round(min_num_instances())
    else:
        self._min_num_instances = min_num_instances

    if callable(max_num_instances):
        self._max_num_instances = round(max_num_instances())
    else:
        self._max_num_instances = max_num_instances

    self._containers: List[vContainer] = EntityList(label=f"{self} Containers")

    self._loadbalancer = loadbalancer

    for _ in range(self._min_num_instances):
        self.containers.append(
            vContainer(
                self.cpu,
                self.ram,
                self.image_size,
                self.cpu_limit,
                self.ram_limit,
                self.volume_descriptions,
                self.priority,
                self.deamon,
                label=f"{self.label}-{len(self._containers)}",
            )
        )

getContainer()

Get the container instance according to the loadbalancer.

Source code in PyCloudSim\entity\v_microservice.py
262
263
264
def getContainer(self):
    """Get the container instance according to the loadbalancer."""
    return self.loadbalancer.getContainer(self)

horizontal_scale_down(num_instances, at)

Horizontal scale down the microservice by terminating container instances. This can not cause the number of container instances to be less than the minimum number of instances.

Source code in PyCloudSim\entity\v_microservice.py
170
171
172
173
174
175
176
177
178
179
180
181
182
def horizontal_scale_down(self, num_instances: int, at: int | float):
    """Horizontal scale down the microservice by terminating container instances. This can not cause the number of container instances to be less than the minimum number of instances."""
    if self.scaling:
        return

    self._scaling = True

    @self.instant_event(at, label=f"{self} Horizontal Scale Down", priority=-1)
    def _scale_down():
        for i in range(
            min([num_instances, len(self.containers) - self.min_num_instances])
        ):
            self.containers[i].terminate(simulation.now)

horizontal_scale_down_triggered() abstractmethod

Abstract method for evaluating if the microservice should be scaled down horizontally.

Source code in PyCloudSim\entity\v_microservice.py
257
258
259
260
@abstractmethod
def horizontal_scale_down_triggered(self) -> bool:
    """Abstract method for evaluating if the microservice should be scaled down horizontally."""
    pass

horizontal_scale_up(num_instances, at)

Horizontal scale up the microservice by adding new container instances.

Source code in PyCloudSim\entity\v_microservice.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def horizontal_scale_up(self, num_instances: int, at: int | float):
    """Horizontal scale up the microservice by adding new container instances."""

    if self.scaling:
        return

    self._scaling = True

    @self.instant_event(at, label=f"{self} Horizontal Scale Up", priority=-1)
    def _scale_up():
        for _ in range(num_instances):
            self.containers.append(
                vContainer(
                    self.cpu,
                    self.ram,
                    self.image_size,
                    self.cpu_limit,
                    self.ram_limit,
                    self.volume_descriptions,
                    self.priority,
                    self.deamon,
                    label=f"{self.label}-{len(self._containers)}",
                    create_at=simulation.now,
                )
            )
        self._scaling = False

horizontal_scale_up_triggered() abstractmethod

Abstract method for evaluating if the microservice should be scaled up horizontally.

Source code in PyCloudSim\entity\v_microservice.py
252
253
254
255
@abstractmethod
def horizontal_scale_up_triggered(self) -> bool:
    """Abstract method for evaluating if the microservice should be scaled up horizontally."""
    pass

on_creation()

Creation procedure of the microservice. It will create the container instances and the evaluator.

Source code in PyCloudSim\entity\v_microservice.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
def on_creation(self):
    """Creation procedure of the microservice. It will create the container instances and the evaluator."""
    for container in self._containers:
        container.create(simulation.now)

    @self.continuous_event(
        at=simulation.now,
        interval=simulation.min_time_unit,
        duration=inf,
        label=f"{self} Evaluator",
    )
    def _evaluator():
        initiated_containers = [
            container for container in self._containers if container.initiated
        ]
        # check if the microservice is ready
        if len(initiated_containers) < self.min_num_instances:
            if self.ready:
                self.state.remove(Constants.READY)
                for _ in range(self.min_num_instances - len(initiated_containers)):
                    self.containers.append(
                        vContainer(
                            self.cpu,
                            self.ram,
                            self.image_size,
                            self.cpu_limit,
                            self.ram_limit,
                            self.volume_descriptions,
                            self.priority,
                            self.deamon,
                            label=f"{self.label}-{len(self._containers)}",
                            create_at=simulation.now,
                        )
                    )
                logger.info(f"{simulation.now}:\t{self} is not ready, recreating {self.min_num_instances - len(initiated_containers)} container instances")
            return
        else:
            if not self.ready:
                self.state.append(Constants.READY)
                logger.info(f"{simulation.now}:\t{self} is ready")

        # check if any container instance is pending:
        if len(initiated_containers) != len(self.containers):
            # if any instance is pending, skip the scaling evaluation
            return

        # check if the microservice should be scaled up
        if len(self.containers) < self.max_num_instances:
            if self.horizontal_scale_up_triggered():
                self.horizontal_scale_up(1, simulation.now)
                return

        # check if the microservice should be scaled down
        if len(self.containers) > self.min_num_instances:
            if self.horizontal_scale_down_triggered():
                self.horizontal_scale_down(1, simulation.now)
                return

vertical_scale(at, cpu, ram, image_size, cpu_limit=None, ram_limit=None, init_delay=0, priority=0, deamon=False, min_num_instances=1, max_num_instances=3, evaluation_interval=0.1, cpu_upper_threshold=0.8, cpu_lower_threshold=0.2, ram_upper_threshold=0.8, ram_lower_threshold=0.2)

Scaling the microservice vertically by changing the attributes of the microservice. This will terminate all the current container instances and create new container instances with the new attributes.

Source code in PyCloudSim\entity\v_microservice.py
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
def vertical_scale(
    self,
    at: int | float,
    cpu: int | Callable[..., int],
    ram: int | Callable[..., int],
    image_size: int | Callable[..., int],
    cpu_limit: int | Callable[..., int] | None = None,
    ram_limit: int | Callable[..., int] | None = None,
    init_delay: int | float | Callable[..., int] | Callable[..., float] = 0,
    priority: int | Callable[..., int] = 0,
    deamon: bool | Callable[..., bool] = False,
    min_num_instances: int | Callable[..., int] = 1,
    max_num_instances: int | Callable[..., int] = 3,
    evaluation_interval: int
    | float
    | Callable[..., int]
    | Callable[..., float] = 0.1,
    cpu_upper_threshold: float | Callable[..., float] = 0.8,
    cpu_lower_threshold: float | Callable[..., float] = 0.2,
    ram_upper_threshold: float | Callable[..., float] = 0.8,
    ram_lower_threshold: float | Callable[..., float] = 0.2,
):
    """Scaling the microservice vertically by changing the attributes of the microservice. This will terminate all the current container instances and create new container instances with the new attributes."""

    @self.instant_event(at, label=f"{self} Vertical Scale", priority=-1)
    def _vertical_scale():
        # update the attributes
        self._cpu = cpu
        self._ram = ram
        self._image_size = image_size
        self._cpu_limit = cpu_limit
        self._ram_limit = ram_limit
        self._priority = priority
        self._demmon = deamon
        self._scaling = False

        if callable(min_num_instances):
            self._min_num_instances = round(min_num_instances())
        else:
            self._min_num_instances = min_num_instances

        if callable(max_num_instances):
            self._max_num_instances = round(max_num_instances())
        else:
            self._max_num_instances = max_num_instances

        # record the current number of instances
        number_instance = len(self.containers)
        # terminate all the current instances
        for container in self.containers:
            container.terminate(simulation.now)
        # create new instances
        for _ in range(number_instance):
            self.containers.append(
                vContainer(
                    self.cpu,
                    self.ram,
                    self.image_size,
                    self.cpu_limit,
                    self.ram_limit,
                    self.volume_descriptions,
                    self.priority,
                    self.deamon,
                    label=f"{self.label}-{len(self._containers)}",
                    create_at=simulation.now,
                )
            )

Default vMicroservice

Bases: vMicroservice

Source code in PyCloudSim\entity\v_microservice.py
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
class vDefaultMicroservice(vMicroservice):
    def __init__(
        self,
        cpu: int | Callable[..., int],
        ram: int | Callable[..., int],
        image_size: int | Callable[..., int],
        cpu_limit: int | Callable[..., int] | None = None,
        ram_limit: int | Callable[..., int] | None = None,
        volumes: List[Tuple[int, str, str]] = [],
        priority: int | Callable[..., int] = 0,
        deamon: bool | Callable[..., bool] = False,
        min_num_instances: int | Callable[..., int] = 1,
        max_num_instances: int | Callable[..., int] = 3,
        loadbalancer: vLoadbalancer = Bestfit(),
        evaluation_interval: int
        | float
        | Callable[..., int]
        | Callable[..., float] = 0.1,
        cpu_upper_threshold: float | Callable[..., float] = 0.8,
        cpu_lower_threshold: float | Callable[..., float] = 0.2,
        ram_upper_threshold: float | Callable[..., float] = 0.8,
        ram_lower_threshold: float | Callable[..., float] = 0.2,
        label: str | None = None,
        create_at: int
        | float
        | Callable[..., int]
        | Callable[..., float]
        | None = None,
        terminate_at: int
        | float
        | Callable[..., int]
        | Callable[..., float]
        | None = None,
        precursor: Entity | List[Entity] | None = None,
    ) -> None:
        """Default microservice. It will scale up if CPU or RAM utilization reached upper threshold. It will scale down if CPU and RAM utilization reached lower threshold."""
        super().__init__(
            cpu,
            ram,
            image_size,
            cpu_limit,
            ram_limit,
            volumes,
            priority,
            deamon,
            min_num_instances,
            max_num_instances,
            loadbalancer,
            label,
            create_at,
            terminate_at,
            precursor,
        )

        if callable(cpu_upper_threshold):
            self._cpu_upper_threshold = cpu_upper_threshold()
        else:
            self._cpu_upper_threshold = cpu_upper_threshold

        if callable(cpu_lower_threshold):
            self._cpu_lower_threshold = cpu_lower_threshold()
        else:
            self._cpu_lower_threshold = cpu_lower_threshold

        if callable(ram_upper_threshold):
            self._ram_upper_threshold = ram_upper_threshold()
        else:
            self._ram_upper_threshold = ram_upper_threshold

        if callable(ram_lower_threshold):
            self._ram_lower_threshold = ram_lower_threshold()
        else:
            self._ram_lower_threshold = ram_lower_threshold

    def horizontal_scale_up_triggered(self) -> bool:
        """The microservice will be scaled up if CPU or RAM utilization reached upper threshold."""
        if (
            self.cpu_utilization >= self.cpu_upper_threshold
            or self.ram_utilization >= self.ram_upper_threshold
        ):
            return True
        else:
            return False

    def horizontal_scale_down_triggered(self) -> bool:
        """The microservice will be scaled down if CPU and RAM utilization reached lower threshold."""
        if (
            self.cpu_utilization <= self.cpu_lower_threshold
            and self.ram_utilization <= self.ram_lower_threshold
        ):
            return True
        else:
            return False

    @property
    def cpu_upper_threshold(self):
        """Return the CPU upper threshold. If CPU utilization reached this threshold, the microservice will be scaled up."""
        return self._cpu_upper_threshold

    @property
    def cpu_lower_threshold(self):
        """Return the CPU lower threshold. If CPU utilization reached this threshold, the microservice will be scaled down (if RAM utilization also reached lower threshold)."""
        return self._cpu_lower_threshold

    @property
    def ram_upper_threshold(self):
        """Return the RAM upper threshold. If RAM utilization reached this threshold, the microservice will be scaled up."""
        return self._ram_upper_threshold

    @property
    def ram_lower_threshold(self):
        """Return the RAM lower threshold. If RAM utilization reached this threshold, the microservice will be scaled down (if CPU utilization also reached lower threshold)."""
        return self._ram_lower_threshold

cpu_lower_threshold property

Return the CPU lower threshold. If CPU utilization reached this threshold, the microservice will be scaled down (if RAM utilization also reached lower threshold).

cpu_upper_threshold property

Return the CPU upper threshold. If CPU utilization reached this threshold, the microservice will be scaled up.

ram_lower_threshold property

Return the RAM lower threshold. If RAM utilization reached this threshold, the microservice will be scaled down (if CPU utilization also reached lower threshold).

ram_upper_threshold property

Return the RAM upper threshold. If RAM utilization reached this threshold, the microservice will be scaled up.

__init__(cpu, ram, image_size, cpu_limit=None, ram_limit=None, volumes=[], priority=0, deamon=False, min_num_instances=1, max_num_instances=3, loadbalancer=Bestfit(), evaluation_interval=0.1, cpu_upper_threshold=0.8, cpu_lower_threshold=0.2, ram_upper_threshold=0.8, ram_lower_threshold=0.2, label=None, create_at=None, terminate_at=None, precursor=None)

Default microservice. It will scale up if CPU or RAM utilization reached upper threshold. It will scale down if CPU and RAM utilization reached lower threshold.

Source code in PyCloudSim\entity\v_microservice.py
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
def __init__(
    self,
    cpu: int | Callable[..., int],
    ram: int | Callable[..., int],
    image_size: int | Callable[..., int],
    cpu_limit: int | Callable[..., int] | None = None,
    ram_limit: int | Callable[..., int] | None = None,
    volumes: List[Tuple[int, str, str]] = [],
    priority: int | Callable[..., int] = 0,
    deamon: bool | Callable[..., bool] = False,
    min_num_instances: int | Callable[..., int] = 1,
    max_num_instances: int | Callable[..., int] = 3,
    loadbalancer: vLoadbalancer = Bestfit(),
    evaluation_interval: int
    | float
    | Callable[..., int]
    | Callable[..., float] = 0.1,
    cpu_upper_threshold: float | Callable[..., float] = 0.8,
    cpu_lower_threshold: float | Callable[..., float] = 0.2,
    ram_upper_threshold: float | Callable[..., float] = 0.8,
    ram_lower_threshold: float | Callable[..., float] = 0.2,
    label: str | None = None,
    create_at: int
    | float
    | Callable[..., int]
    | Callable[..., float]
    | None = None,
    terminate_at: int
    | float
    | Callable[..., int]
    | Callable[..., float]
    | None = None,
    precursor: Entity | List[Entity] | None = None,
) -> None:
    """Default microservice. It will scale up if CPU or RAM utilization reached upper threshold. It will scale down if CPU and RAM utilization reached lower threshold."""
    super().__init__(
        cpu,
        ram,
        image_size,
        cpu_limit,
        ram_limit,
        volumes,
        priority,
        deamon,
        min_num_instances,
        max_num_instances,
        loadbalancer,
        label,
        create_at,
        terminate_at,
        precursor,
    )

    if callable(cpu_upper_threshold):
        self._cpu_upper_threshold = cpu_upper_threshold()
    else:
        self._cpu_upper_threshold = cpu_upper_threshold

    if callable(cpu_lower_threshold):
        self._cpu_lower_threshold = cpu_lower_threshold()
    else:
        self._cpu_lower_threshold = cpu_lower_threshold

    if callable(ram_upper_threshold):
        self._ram_upper_threshold = ram_upper_threshold()
    else:
        self._ram_upper_threshold = ram_upper_threshold

    if callable(ram_lower_threshold):
        self._ram_lower_threshold = ram_lower_threshold()
    else:
        self._ram_lower_threshold = ram_lower_threshold

horizontal_scale_down_triggered()

The microservice will be scaled down if CPU and RAM utilization reached lower threshold.

Source code in PyCloudSim\entity\v_microservice.py
521
522
523
524
525
526
527
528
529
def horizontal_scale_down_triggered(self) -> bool:
    """The microservice will be scaled down if CPU and RAM utilization reached lower threshold."""
    if (
        self.cpu_utilization <= self.cpu_lower_threshold
        and self.ram_utilization <= self.ram_lower_threshold
    ):
        return True
    else:
        return False

horizontal_scale_up_triggered()

The microservice will be scaled up if CPU or RAM utilization reached upper threshold.

Source code in PyCloudSim\entity\v_microservice.py
511
512
513
514
515
516
517
518
519
def horizontal_scale_up_triggered(self) -> bool:
    """The microservice will be scaled up if CPU or RAM utilization reached upper threshold."""
    if (
        self.cpu_utilization >= self.cpu_upper_threshold
        or self.ram_utilization >= self.ram_upper_threshold
    ):
        return True
    else:
        return False