The scheduler (or allocator) is a core component of CloudStack, responsible for determining:

  • Which host a VM should run on
  • Which StoragePool a volume should be stored in
  • Network resource availability
  • How to avoid unhealthy or resource-insufficient nodes
  • How to work with the Orchestration Engine to perform complex deployments

1. Scheduling System Architecture Overview (Source Code Location)

The CloudStack scheduler is divided into three layers:

1. DeploymentPlanningManager (responsible for the overall scheduling entry point of orchestrateDeployVM)
2. Host Allocator (selects hosts)
3. StoragePool Allocator (selects storage pools)

Source Code Path:

engine/orchestration/src/com/cloud/deploy/
    ├── DeploymentPlanningManagerImpl.java
    ├── FirstFitPlanner.java
    ├── ClusterBasedPlanner.java

server/src/com/cloud/agent/manager/allocator/
    ├── HostAllocator.java
    ├── FirstFitAllocator.java

engine/storage/src/com/cloud/storage/allocator/
    ├── StoragePoolAllocator.java
    ├── FirstFitStoragePoolAllocator.java

2. DeploymentPlanningManager:Dispatch Entry

2.1 Dispatch chain

VM Dispatch Chain:

orchestrateDeployVM()
 → DeploymentPlanningManager.plan()
    → Planner.design()
    → HostAllocator.getHostsToUse()
    → StoragePoolAllocator.select()

Key methods:

@Override
public DeployDestination plan(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) {
    DataCenter dc = _dcDao.findById(plan.getDataCenterId());
    List<Planner> planners = getPlanners(offering, vmProfile);

    for (Planner planner : planners) {
        DeployDestination dest = planner.plan(vmProfile, plan, avoid);
        if (dest != null) return dest;
    }
    throw new InsufficientServerCapacityException(...);
}

3. Planner(Level 1 Scheduling)

The Planner determines which algorithm to use to select resources.

CloudStack Default Planner:

  • FirstFitPlanner(Most commonly used)
  • ClusterBasedPlanner
  • ImplicitPlanner

3.1 FirstFitPlanner Key Logic

Located at:

engine/orchestration/com/cloud/deploy/FirstFitPlanner.java

Souce code:

public DeployDestination plan(...) {
    List<Cluster> clusters = listAllClusters();
    for (Cluster c : clusters) {
        Host host = findHost(c, vmProfile);
        StoragePool pool = findPool(c, vmProfile);
        if (host != null && pool != null) {
            return new DeployDestination(dc, pod, c, host, pool);
        }
    }
    return null;
}

FirstFit = Find the first cluster that meets the CPU/MEM/Storage criteria.

The Planner determines the overall direction, but the Allocator below is responsible for providing the actual candidate resources.

4. HostAllocator

Located at:

server/src/com/cloud/agent/manager/allocator/HostAllocator.java

Main implementations:

  • FirstFitAllocator
  • UserConcentratedPodAllocator (selects hosts based on user concentration)
  • RandomAllocator (random selection)

Key interfaces:

List<Host> allocateTo(VirtualMachineProfile vm, DeployDestination dest, ExcludeList avoid);

4.1 FirstFitAllocator implementation

Key function:

hosts = _hostDao.listAllUpAndEnabledByCluster(clusterId);

for (Host host : hosts) {
    if (checkHostCapacity(host, vmProfile) &&
        !avoid.shouldAvoid(host)) {
        return Arrays.asList(host);
    }
}
return null;

Check CPU and MEM:

host.getTotalMemory() - host.getUsedMemory() > vmMemRequired
host.getCpus() * host.getCpuSpeed() > vmCpuRequired

Additionally, the following will be checked:

  • Whether the host is in maintenance mode
  • Whether the host is compatible with the hypervisor
  • Whether the network can be routed from this host

5. StoragePoolAllocator

Storage scheduling is also modular:

StoragePoolAllocator
  ├── FirstFitStoragePoolAllocator
  ├── LocalStoragePoolAllocator
  └── ClusterScopeStorageAllocator

Key interface:

List<StoragePool> select(VirtualMachineProfile vm, Long dataCenterId, Long podId, Long clusterId);

5.1 FirstFitStoragePoolAllocator

Souce code:

for (StoragePoolVO pool : availablePools) {
    if (pool.getStatus() == Status.Up &&
        pool.getAvailableSpace() > volumeSize &&
        checkTags(pool, vm)) {
        return Arrays.asList(pool);
    }
}

Scheduling factors:

  • Pool capacity
  • Pool reachability (network topology)
  • Storage tags
  • Template existence in the pool

6. Network Allocator

Scheduling also requires verifying whether the network can operate on the target host.

Schedule chain:

DeploymentPlanningManager.plan()
 → _networkModel.isVmNetworksPresentOnHost(vm, host)

Network matching logic:

List<NicProfile> nics = vm.getNics();
for (NicProfile nic : nics) {
    if (!networkAvailableOnHost(nic.getNetwork(), host)) return false;
}
return true;

Network reachability includes:

  • BroadcastDomain type matching
  • Whether the VLAN is trunked on the target host
  • Whether the VR exists and can serve this host

7. ExcludeList

ExcludeList is a crucial but often overlooked structure in scheduling.

It is used to record resources that should not be used.

hostsToAvoid
poolsToAvoid
clustersToAvoid
podsToAvoid

When scheduling fails:

avoid.addHost(hostId);
avoid.addPool(poolId);

Retry scheduling will avoid problematic resources based on the ExcludeList.

8. Complete scheduling sequence diagram

orchestrateDeployVM
 |
 v
DeploymentPlanningManager.plan()
 |
 +--> FirstFitPlanner.plan()
 |       |
 |       +--> HostAllocator.allocateTo()
 |       |       |
 |       |       +--> check CPU/MEM/capacity
 |       |       +--> avoid list
 |       |
 |       +--> StoragePoolAllocator.select()
 |               |
 |               +--> check space/tags/pool status
 |
 +--> Build DeployDestination(dc,pod,cluster,host,pool)

9. Scheduling failure

9.1 Host has no available resources

InsufficientServerCapacityException

Reasons:

  • Insufficient CPU/MEM
  • Host is in maintenance mode
  • AvoidList avoids all hosts

9.2 StoragePool FULL

No suitable storage pool

Check:

storage_pool.used_bytes
storage_pool.capacity_bytes

9.3 Network unreachable

Network is not available on host

Check VLAN trunk and VR status.

10. Host / Storage Capacity Table Structure

10.1 op_host_capacity

Storage host capacity information:

host_id
capacity_type
total_capacity
used_capacity

Update capacity after VM starts:

UPDATE op_host_capacity SET used += vm_mem

10.2 storage_pool

id
available_bytes
capacity_bytes
status
scope

11. Summary of Key Scheduling Classes

Hierarchy Class Function
Scheduling Entry Point DeploymentPlanningManager Calls Planner
Planner FirstFitPlanner Overall Scheduling Strategy
HostAllocator FirstFitAllocator Host Selection
StorageAllocator FirstFitStoragePoolAllocator Storage Pool Selection
Network Authentication NetworkModelImpl VLAN/trunk/VR Check
ExcludeList ExcludeList Dynamically Avoids Bad Hosts/Pools

12. Summary

CloudStack’s scheduling system is not a single-layer algorithm, but a multi-layer collaborative structure:

  • Planner → Allocators → NetworkModel → ExcludeList
  • Joint decision-making across CPU/MEM/Storage/Network
  • Pluggable HostAllocator / StoragePoolAllocator
  • ExcludeList provides “dynamic learning” capabilities