Skip to content

vContainer

The class "vContainer" serves as an implementation of the abstract class "VirtualEntity" and emulates containers in Docker or Pods in Kubernetes. It encompasses the following essential attributes and member functions:

  1. CPU: Represents the CPU time limit allocated to the "vContainer".
  2. RAM: Denotes the maximum amount of RAM that the "vContainer" can utilize.
  3. Simulated API Call Queue: Stores the simulated API calls associated with the "vContainer".
  4. Simulated Process Queue: Holds the simulated processes assigned to the "vContainer".
  5. Crash Handling: If the RAM consumed by all the simulated processes in the queue surpasses the container's RAM capacity, the "vContainer" will crash. Consequently, all processes in the queue will be terminated and marked as failed.
  6. Simulated Daemon Process: The "vContainer" may include a simulated daemon process that mimics resource usage when the container is idle. This daemon process operates continuously until the "vContainer" is terminated.

Overall, the "vContainer" encapsulates the behavior and characteristics of containerized environments, providing capabilities for resource allocation, process management, and crash handling within the simulated cloud environment.

Bases: vSoftwareEntity

Source code in PyCloudSim\entity\v_container.py
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 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
class vContainer(vSoftwareEntity):
    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,
        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:
        """Create a simulated container.

        Args:
            cpu (int | Callable[..., int]): the requested CPU of the container.
            ram (int | Callable[..., int]): the requested RAM of the container.
            image_size (int | Callable[..., int]): the image size of the container.
            cpu_limit (int | Callable[..., int] | None, optional): the limited CPU of the container. Defaults to None, means there is no limitation.
            ram_limit (int | Callable[..., int] | None, optional): the limited RAM of the container. Defaults to None, means there is no limitation.
            priority (int | Callable[..., int], optional): the priority of the container. Defaults to 0.
            deamon (bool | Callable[..., bool], optional): true if the container has a constantly running process. Defaults to False.
            label (str | None, optional): the short description of the container. Defaults to None.
            create_at (int | float | Callable[..., int] | Callable[..., float] | None, optional): when this container should be created. Defaults to None.
            terminate_at (int | float | Callable[..., int] | Callable[..., float] | None, optional): when this container should be terminated. Defaults to None means it will not be terminated unless it is failed or termination is forced.
            precursor (Entity | List[Entity] | None, optional): the entity that this container must not be created before. Defaults to None.
        """
        super().__init__(label, create_at, terminate_at, precursor)

        if callable(cpu):
            self._cpu = round(cpu())
        else:
            self._cpu = cpu

        if callable(ram):
            self._ram = MiB(round(ram())).bytes
        else:
            self._ram = MiB(ram).bytes

        if callable(image_size):
            self._image_size = MiB(round(image_size())).bytes
        else:
            self._image_size = MiB(image_size).bytes

        if callable(ram_limit):
            self._ram_limit = MiB(round(ram_limit())).bytes
        elif ram_limit is not None:
            self._ram_limit = MiB(ram_limit).bytes
        else:
            self._ram_limit = inf

        if callable(cpu_limit):
            self._cpu_limit = round(cpu_limit())
        elif cpu_limit is not None:
            self._cpu_limit = cpu_limit
        else:
            self._cpu_limit = inf

        self._volumes_descriptions = volumes
        self._volumes = EntityList(label=f"{self} Volumes")

        if callable(priority):
            self._priority = round(priority())
        else:
            self._priority = priority

        if callable(deamon):
            self._deamon = deamon()
        else:
            self._deamon = deamon

        self._host: vHost | None = None
        self._deamon_process: vProcess | None = None
        self._process_queue: List[vProcess] = EntityList(label=f"{self} Process Queue")
        self._cpu_usage = 0.0
        self._ram_usage = 0

        simulation.containers.append(self)

    def on_creation(self):
        for volume_description in self._volumes_descriptions:
            volume = vVolume(
                size=volume_description[0],
                path=volume_description[1],
                label=volume_description[2],
                create_at=simulation.now,
            )
            self.volumes.append(volume)

        logger.info(f"{simulation.now}:\t{self} is created.")

    def on_termination(self):
        for process in self.process_queue:
            process.fail(simulation.now)
        for volume in self.volumes:
            volume.terminate(simulation.now)
        logger.info(f"{simulation.now}:\t{self} is terminated.")

    def on_destruction(self):
        for process in self.process_queue:
            process.fail(simulation.now)
        for volume in self.volumes:
            volume.destroy(simulation.now)
        logger.info(f"{simulation.now}:\t{self} is failed.")

    def on_success(self) -> None:
        super().on_success()

    def on_fail(self) -> None:
        super().on_fail()
        logger.info(f"{simulation.now}:\t{self} is failed.")

    def on_initiate(self):
        """Initiate the container."""
        super().on_initiate()
        if self.host is None:
            raise RuntimeError(f"{self} can not be initiated without a host.")
        if self.deamon:
            deamon_length = round(
                (self.cpu / 1000) * self.host.cpu.ipc * self.host.cpu.frequency
            )
            self._deamon_process = vDeamon(
                length=deamon_length,
                container=self,
                priority=-1,
                label=f"{self.label}",
                create_at=simulation.now,
            )
        logger.info(f"{simulation.now}:\t{self} is initiated.")

    @property
    def cpu(self):
        """Return the requested CPU of the container."""
        return self._cpu

    @property
    def cpu_limit(self) -> float | int:
        """Return the CPU limit of the container."""
        return self._cpu_limit

    @property
    def ram(self):
        """Return the requested RAM of the container."""
        return self._ram

    @property
    def ram_limit(self) -> float | int:
        """Return the RAM limit of the container."""
        return self._ram_limit

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

    @property
    def priority(self):
        """Return the priority of the container."""
        return self._priority

    @property
    def scheduled(self):
        """Return whether the container has been scheduled."""
        return Constants.SCHEDULED in self.state

    @property
    def initiated(self):
        """Return whether the container has been initiated."""
        return Constants.INITIATED in self.state

    @property
    def deamon(self):
        """Return whether the container is a deamon."""
        return self._deamon

    @property
    def deamon_process(self):
        """Return the deamon process of the container."""
        return self._deamon_process

    @property
    def host(self):
        """Return the host of the container."""
        if self._host is None:
            raise RuntimeError(f"{self} has not been allocated on a host.")
        return self._host

    @property
    def cpu_usage(self):
        """Return the CPU usage of the container."""
        return self._cpu_usage

    @property
    def cpu_utilization(self):
        """Return the CPU utilization of the container."""
        return self._cpu_usage / self.cpu_limit

    @property
    def ram_usage(self):
        """Return the RAM usage of the container."""
        return self._ram_usage

    @property
    def ram_utilization(self):
        """Return the RAM utilization of the container."""
        return self._ram_usage / self.ram_limit

    @property
    def process_queue(self):
        """Return the process queue of the container."""
        return self._process_queue

    @property
    def volumes(self):
        """Return the volumes of the container."""
        return self._volumes

cpu property

Return the requested CPU of the container.

cpu_limit: float | int property

Return the CPU limit of the container.

cpu_usage property

Return the CPU usage of the container.

cpu_utilization property

Return the CPU utilization of the container.

deamon property

Return whether the container is a deamon.

deamon_process property

Return the deamon process of the container.

host property

Return the host of the container.

image_size property

Return the image size of the container.

initiated property

Return whether the container has been initiated.

priority property

Return the priority of the container.

process_queue property

Return the process queue of the container.

ram property

Return the requested RAM of the container.

ram_limit: float | int property

Return the RAM limit of the container.

ram_usage property

Return the RAM usage of the container.

ram_utilization property

Return the RAM utilization of the container.

scheduled property

Return whether the container has been scheduled.

volumes property

Return the volumes of the container.

__init__(cpu, ram, image_size, cpu_limit=None, ram_limit=None, volumes=[], priority=0, deamon=False, label=None, create_at=None, terminate_at=None, precursor=None)

Create a simulated container.

Parameters:

Name Type Description Default
cpu int | Callable[..., int]

the requested CPU of the container.

required
ram int | Callable[..., int]

the requested RAM of the container.

required
image_size int | Callable[..., int]

the image size of the container.

required
cpu_limit int | Callable[..., int] | None

the limited CPU of the container. Defaults to None, means there is no limitation.

None
ram_limit int | Callable[..., int] | None

the limited RAM of the container. Defaults to None, means there is no limitation.

None
priority int | Callable[..., int]

the priority of the container. Defaults to 0.

0
deamon bool | Callable[..., bool]

true if the container has a constantly running process. Defaults to False.

False
label str | None

the short description of the container. Defaults to None.

None
create_at int | float | Callable[..., int] | Callable[..., float] | None

when this container should be created. Defaults to None.

None
terminate_at int | float | Callable[..., int] | Callable[..., float] | None

when this container should be terminated. Defaults to None means it will not be terminated unless it is failed or termination is forced.

None
precursor Entity | List[Entity] | None

the entity that this container must not be created before. Defaults to None.

None
Source code in PyCloudSim\entity\v_container.py
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 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
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,
    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:
    """Create a simulated container.

    Args:
        cpu (int | Callable[..., int]): the requested CPU of the container.
        ram (int | Callable[..., int]): the requested RAM of the container.
        image_size (int | Callable[..., int]): the image size of the container.
        cpu_limit (int | Callable[..., int] | None, optional): the limited CPU of the container. Defaults to None, means there is no limitation.
        ram_limit (int | Callable[..., int] | None, optional): the limited RAM of the container. Defaults to None, means there is no limitation.
        priority (int | Callable[..., int], optional): the priority of the container. Defaults to 0.
        deamon (bool | Callable[..., bool], optional): true if the container has a constantly running process. Defaults to False.
        label (str | None, optional): the short description of the container. Defaults to None.
        create_at (int | float | Callable[..., int] | Callable[..., float] | None, optional): when this container should be created. Defaults to None.
        terminate_at (int | float | Callable[..., int] | Callable[..., float] | None, optional): when this container should be terminated. Defaults to None means it will not be terminated unless it is failed or termination is forced.
        precursor (Entity | List[Entity] | None, optional): the entity that this container must not be created before. Defaults to None.
    """
    super().__init__(label, create_at, terminate_at, precursor)

    if callable(cpu):
        self._cpu = round(cpu())
    else:
        self._cpu = cpu

    if callable(ram):
        self._ram = MiB(round(ram())).bytes
    else:
        self._ram = MiB(ram).bytes

    if callable(image_size):
        self._image_size = MiB(round(image_size())).bytes
    else:
        self._image_size = MiB(image_size).bytes

    if callable(ram_limit):
        self._ram_limit = MiB(round(ram_limit())).bytes
    elif ram_limit is not None:
        self._ram_limit = MiB(ram_limit).bytes
    else:
        self._ram_limit = inf

    if callable(cpu_limit):
        self._cpu_limit = round(cpu_limit())
    elif cpu_limit is not None:
        self._cpu_limit = cpu_limit
    else:
        self._cpu_limit = inf

    self._volumes_descriptions = volumes
    self._volumes = EntityList(label=f"{self} Volumes")

    if callable(priority):
        self._priority = round(priority())
    else:
        self._priority = priority

    if callable(deamon):
        self._deamon = deamon()
    else:
        self._deamon = deamon

    self._host: vHost | None = None
    self._deamon_process: vProcess | None = None
    self._process_queue: List[vProcess] = EntityList(label=f"{self} Process Queue")
    self._cpu_usage = 0.0
    self._ram_usage = 0

    simulation.containers.append(self)

on_initiate()

Initiate the container.

Source code in PyCloudSim\entity\v_container.py
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def on_initiate(self):
    """Initiate the container."""
    super().on_initiate()
    if self.host is None:
        raise RuntimeError(f"{self} can not be initiated without a host.")
    if self.deamon:
        deamon_length = round(
            (self.cpu / 1000) * self.host.cpu.ipc * self.host.cpu.frequency
        )
        self._deamon_process = vDeamon(
            length=deamon_length,
            container=self,
            priority=-1,
            label=f"{self.label}",
            create_at=simulation.now,
        )
    logger.info(f"{simulation.now}:\t{self} is initiated.")