Skip to content

Container Scheduler

The "ContainerScheduler" class is responsible for allocating suitable "vHost" instances to "vContainer" instances based on the available CPU and RAM resources. The scheduling process is implemented as an event that is triggered whenever a new "vContainer" is created or a "vContainer" is terminated. Only one scheduling process can exist at any time during the simulation.

The "ContainerScheduler" class includes an abstract member function called "findHost", which allows developers to customize the conditions for determining which "vHost" instances are eligible for hosting a specific "vContainer". By implementing the "findHost" function, different scheduling strategies can be employed based on specific requirements and constraints.

PyCloudSim provides several default schedulers that can be used with the "ContainerScheduler" class:

  1. "Bestfit" scheduler: This scheduler finds the most utilized "vHost" instance that still has available resources to host the "vContainer" being scheduled.
  2. "Worstfit" scheduler: This scheduler finds the most underutilized "vHost" instance that still has available resources to host the "vContainer" being scheduled.
  3. "Random" scheduler: This scheduler allocates the "vContainer" to a random "vHost" instance that has sufficient resources.

Only one "ContainerScheduler" can be defined and used in the simulation. If multiple "ContainerScheduler" instances are initialized, the last one defined will be used during the simulation.

The general procedure followed by the "ContainerScheduler" involves evaluating the available resources of each "vHost" instance and selecting the most suitable "vHost" to host the "vContainer" based on the defined scheduling strategy. This process ensures efficient resource allocation and utilization in the simulated cloud environment.

ContainerScheduler

Bases: ABC

Source code in PyCloudSim\scheduler\container_scheduler.py
class ContainerScheduler(ABC):
    __host_affinity: bool

    def __init__(
        self,
        host_affinity: bool = False,
    ) -> None:
        """Base class for container schedulers.

        Args:
            host_affinity (bool, optional): set to true for host affinity scheduling, that the host and container must have the same taint. Defaults to False.
        """        
        self._host_affinity = host_affinity
        self._active_process: Actor = None  # type: ignore
        simulation._container_scheduler = self

    @abstractmethod
    def find_host(self, container: vContainer) -> Union[vHost, None]:
        """Abstract function to be implemented with your specific container scheduling algorithm."""
        pass

    def schedule(self):
        """Event function to be called by the simulation engine to schedule containers. find_host() is called automatically by this function."""
        def _schedule():
            self._active_process = None  # type: ignore
            for container in simulation.CONTAINERS:
                if (
                    container.scheduled
                    or container.terminated
                    or not container.schedulable
                ):
                    continue

                if candidate_host := self.find_host(container):
                    candidate_host.allocate_container(container)

                if not container.scheduled:
                    LOGGER.info(
                        f"{simulation.now:0.2f}\tvContainer {container.label} can not be shceduled, privisioning new vHost if possible."
                    )
                    if self.host_affinity:
                        for host in simulation.HOSTS:
                            if host.taint == container.taint:
                                simulation.host_privisioner.privision(host)

                    else:
                        for host in simulation.HOSTS:
                            if host.powered_off:
                                simulation.host_privisioner.privision(host)

        if self.active_process is None:
            self._active_process = Actor(
                at=simulation.now,
                action=_schedule,
                label=f"vContainer Scheduling",
                priority=CONTAINER_SCHEDULER,
            )

    @property
    def host_affinity(self) -> bool:
        """returns True if host affinity is enabled, False otherwise."""
        return self._host_affinity

    @property
    def active_process(self) -> Actor:
        """returns the active process of the scheduler."""
        return self._active_process

active_process: Actor property

returns the active process of the scheduler.

host_affinity: bool property

returns True if host affinity is enabled, False otherwise.

__init__(host_affinity=False)

Base class for container schedulers.

Parameters:

Name Type Description Default
host_affinity bool

set to true for host affinity scheduling, that the host and container must have the same taint. Defaults to False.

False
Source code in PyCloudSim\scheduler\container_scheduler.py
def __init__(
    self,
    host_affinity: bool = False,
) -> None:
    """Base class for container schedulers.

    Args:
        host_affinity (bool, optional): set to true for host affinity scheduling, that the host and container must have the same taint. Defaults to False.
    """        
    self._host_affinity = host_affinity
    self._active_process: Actor = None  # type: ignore
    simulation._container_scheduler = self

find_host(container) abstractmethod

Abstract function to be implemented with your specific container scheduling algorithm.

Source code in PyCloudSim\scheduler\container_scheduler.py
@abstractmethod
def find_host(self, container: vContainer) -> Union[vHost, None]:
    """Abstract function to be implemented with your specific container scheduling algorithm."""
    pass

schedule()

Event function to be called by the simulation engine to schedule containers. find_host() is called automatically by this function.

Source code in PyCloudSim\scheduler\container_scheduler.py
def schedule(self):
    """Event function to be called by the simulation engine to schedule containers. find_host() is called automatically by this function."""
    def _schedule():
        self._active_process = None  # type: ignore
        for container in simulation.CONTAINERS:
            if (
                container.scheduled
                or container.terminated
                or not container.schedulable
            ):
                continue

            if candidate_host := self.find_host(container):
                candidate_host.allocate_container(container)

            if not container.scheduled:
                LOGGER.info(
                    f"{simulation.now:0.2f}\tvContainer {container.label} can not be shceduled, privisioning new vHost if possible."
                )
                if self.host_affinity:
                    for host in simulation.HOSTS:
                        if host.taint == container.taint:
                            simulation.host_privisioner.privision(host)

                else:
                    for host in simulation.HOSTS:
                        if host.powered_off:
                            simulation.host_privisioner.privision(host)

    if self.active_process is None:
        self._active_process = Actor(
            at=simulation.now,
            action=_schedule,
            label=f"vContainer Scheduling",
            priority=CONTAINER_SCHEDULER,
        )

ContainerSchedulerBestfit

Bases: ContainerScheduler

Bestfit container scheduler, that finds the fullest host for the container based on the available resources of the host.

Source code in PyCloudSim\scheduler\container_scheduler.py
class ContainerSchedulerBestfit(ContainerScheduler):
    """Bestfit container scheduler, that finds the fullest host for the container based on the available resources of the host.
    """
    def find_host(self, container: vContainer) -> vHost | None:
        if self._host_affinity:
            candidate_host = [host for host in simulation.HOSTS if host.taint == container.taint and host.powered_on]
            candidate_host.sort(key=lambda host: host.ram.utilization)
            candidate_host.sort(key=lambda host: host.cpu.utilization)
            for host in candidate_host:
                if (
                    host.cpu_reservor.available_quantity >= container.cpu_request
                    and host.ram_reservor.available_quantity
                    >= container.ram_request
                    and host.rom.available_quantity >= container.image_size
                ):
                    LOGGER.debug(
                        f"{simulation.now:0.2f}\tFound vHost {host.label} {host.cpu.availablity} CPU, {host.ram.available_quantity} RAM, {host.rom.available_quantity} ROM for vContainer {container.label} {container.cpu_request} CPU, {container.ram_request} RAM, {container.image_size} ROM"
                    )
                    return host
        else:
            simulation.HOSTS.sort(key=lambda host: host.ram.utilization)
            simulation.HOSTS.sort(key=lambda host: host.cpu.utilization)
            for host in simulation.HOSTS:
                if host.powered_on:
                    if (
                        host.cpu_reservor.available_quantity >= container.cpu_request
                        and host.ram_reservor.available_quantity
                        >= container.ram_request
                        and host.rom.available_quantity >= container.image_size
                    ):
                        LOGGER.debug(
                            f"{simulation.now:0.2f}\tFound vHost {host.label} {host.cpu_reservor.available_quantity} CPU, {host.ram_reservor.available_quantity} RAM, {host.rom.available_quantity} ROM for vContainer {container.label} {container.cpu_request} CPU, {container.ram_request} RAM, {container.image_size} ROM"
                        )
                        return host

        return None

ContainerSchedulerRandom

Bases: ContainerScheduler

Worstfit container scheduler, that finds the most empty host for the container based on the available resources of the host.

Source code in PyCloudSim\scheduler\container_scheduler.py
class ContainerSchedulerRandom(ContainerScheduler):
    """Worstfit container scheduler, that finds the most empty host for the container based on the available resources of the host.
    """
    def find_host(self, container: vContainer) -> vHost | None:
        if self._host_affinity:
            candidate_host = [host for host in simulation.HOSTS if host.taint == container.taint and host.powered_on]
            random.shuffle(candidate_host)
            for host in candidate_host:
                if (
                    host.cpu_reservor.available_quantity >= container.cpu_request
                    and host.ram_reservor.available_quantity
                    >= container.ram_request
                    and host.rom.available_quantity >= container.image_size
                ):
                    LOGGER.debug(
                        f"{simulation.now:0.2f}\tFound vHost {host.label} {host.cpu.availablity} CPU, {host.ram.available_quantity} RAM, {host.rom.available_quantity} ROM for vContainer {container.label} {container.cpu_request} CPU, {container.ram_request} RAM, {container.image_size} ROM"
                    )
                    return host
        else:
            random.shuffle(simulation.HOSTS)
            for host in simulation.HOSTS:
                if host.powered_on:
                    if (
                        host.cpu_reservor.available_quantity >= container.cpu_request
                        and host.ram_reservor.available_quantity
                        >= container.ram_request
                        and host.rom.available_quantity >= container.image_size
                    ):
                        LOGGER.debug(
                            f"{simulation.now:0.2f}\tFound vHost {host.label} {host.cpu_reservor.available_quantity} CPU, {host.ram_reservor.available_quantity} RAM, {host.rom.available_quantity} ROM for vContainer {container.label} {container.cpu_request} CPU, {container.ram_request} RAM, {container.image_size} ROM"
                        )
                        return host

        return None

ContainerSchedulerWorstfit

Bases: ContainerScheduler

Worstfit container scheduler, that finds the most empty host for the container based on the available resources of the host.

Source code in PyCloudSim\scheduler\container_scheduler.py
class ContainerSchedulerWorstfit(ContainerScheduler):
    """Worstfit container scheduler, that finds the most empty host for the container based on the available resources of the host.
    """
    def find_host(self, container: vContainer) -> vHost | None:
        if self._host_affinity:
            candidate_host = [host for host in simulation.HOSTS if host.taint == container.taint and host.powered_on]
            candidate_host.sort(key=lambda host: host.ram.utilization, reverse=True)
            candidate_host.sort(key=lambda host: host.cpu.utilization, reverse=True)
            for host in candidate_host:
                if (
                    host.cpu_reservor.available_quantity >= container.cpu_request
                    and host.ram_reservor.available_quantity
                    >= container.ram_request
                    and host.rom.available_quantity >= container.image_size
                ):
                    LOGGER.debug(
                        f"{simulation.now:0.2f}\tFound vHost {host.label} {host.cpu.availablity} CPU, {host.ram.available_quantity} RAM, {host.rom.available_quantity} ROM for vContainer {container.label} {container.cpu_request} CPU, {container.ram_request} RAM, {container.image_size} ROM"
                    )
                    return host
        else:
            simulation.HOSTS.sort(key=lambda host: host.ram.utilization, reverse=True)
            simulation.HOSTS.sort(key=lambda host: host.cpu.utilization, reverse=True)
            for host in simulation.HOSTS:
                if host.powered_on:
                    if (
                        host.cpu_reservor.available_quantity >= container.cpu_request
                        and host.ram_reservor.available_quantity
                        >= container.ram_request
                        and host.rom.available_quantity >= container.image_size
                    ):
                        LOGGER.debug(
                            f"{simulation.now:0.2f}\tFound vHost {host.label} {host.cpu_reservor.available_quantity} CPU, {host.ram_reservor.available_quantity} RAM, {host.rom.available_quantity} ROM for vContainer {container.label} {container.cpu_request} CPU, {container.ram_request} RAM, {container.image_size} ROM"
                        )
                        return host

        return None