Branch

master, planner_reserve

Introduction

Currently CloudStack has following 3 deployment planners available out-of-the-box:

  • FirstFitPlanner
  • UserDispersingPlanner
  • UserConcentratedPodPlanner

Each of these planners implements some heuristics that provide ordering of resources on some basis, while choosing resources for VM deployment. Currently in a CloudStack deployment, only one of these planners can be used for all VM deployments. The global parameter 'vm.allocation.algorithm' decides which planner will be used.

However there could be a need to be able to choose different planning strategies within a single CS deployment. So letting Admin choose a deployment planner for a set of VMs will be helpful.

To enable this, proposal is:

  • Expose deployment planner as part of a ServiceOffering API. By default, the value can be null and in that case, CS will refer a global configuration variable 'vm.deployment.planner'. But admin can override the global choice and set some other planner for a service offering as per needs.
  • Add a resource reservation mechanism to let deployment planners co-exist

Resource reservation between planners

When the Deployment planner gets exposed per ServiceOffering, then in a CS deployment multiple planners will have to co-exist.

In such case, we might need resource reservation between planners, so that planner executions do not step onto each other's resource choice.

The existing planners work on the available set of resources in a given datacenter that are shared across various accounts. So all of them can co-exist without an issue since they do not need to book resources exclusively.

However if a planner is added that needs to use resources exclusively for an account, then we will need some kind of resource reservation between planners.

e.g Refer to the Implicit Dedication Planner being added as part of this 4.2 release.

Design

  1. Planner Choice in ServiceOffering:
    1. Admin can set a deployment_planner to be used while creating a service offering. Changes are needed to createServiceOffering API to add a deployment_planner.
    2. During VM deployment, each planner can check if it is supposed to execute based on the ServiceOffering of the VM being deployed. DeploymentPlanner :: canHandle() can be modified to do this check.
  2. Reservation Mechanism:
    1. As part of the Affinity feature, a new manager on top of deployment planners is added, called as the DeploymentPlanningManager. This manager can handle the resource reservation as well.
    2. Currently, the DPM invokes the planners to find suitable host and storage pools for the VM being deployed.
    3. After a planner finds a host to use, DPM can make a check if that host is reserved by any planner explicitly or if it can be shared across planners.
    4. When a planner like the [Implicit Dedication Planner] chooses a host for deployment, DPM can store it as a 'dedicated' host. No other planner will be able to pick it up for any other VM deployment.
    5. VMs deployed through FirstFitPlanner, UserDispersingPlanner and UserConcentratedPodPlanner can share hosts - so DPM can mark those hosts as 'shared'.
    6. DPM will store this reservation info in a separate table 'op_host_planner_reservation'
    7. Also in order to free up the reservations, DPM can listen to VM state transitions. When a VM is stopped, DPM can check if the host has no other VMs. If yes, it can free up the reservation so that it can be picked up by other planner.

PlannerResourceUsage

We will add this enum to the DeploymentPlanner interface. Each planner should return the resource usage it works with.

E.g: the existing 3 planners (FirstFit, UserDispersing, UserConcentrated) can share resources - so they will return PlannerResourceUsage.Shared

public enum PlannerResourceUsage { Shared, Dedicated;}

DeploymentClusterPlanner Interface

As noted above, DPM will check if a host selectd by a planner can be used by that planner by referring to the 'op_host_planner_reservation' record and reserve the host if it can be used.

However, if the host has been picked by another planner for a non-matching usage then DPm will have to re-invoke the planners to find new host.

DeploymentPlanners currently list clusters using some heuristic and for each cluster find a list of suitable host and suitable storagepools. From these list the first pair of host and pool that works together is returned. At this point the ordered list of clusters, hosts and storagepools is thrown away. Now if DPM rejects this chosen host at the reservation step at last, we will execute all the planner logic again.

Instead if DPM has access to the list of clusters ordered by the planner, we will save some iterations calling the HostAllocator and StoragePoolAllocators over and over.

Hence we will  introduce a new interface that extends from existing DeploymentPlanner interface that the current planners will implement.

public interface DeploymentClusterPlanner extends DeploymentPlanner {
    /**
     * This is called to determine list of possible clusters where a virtual
     * machine can be deployed.
     *
     * @param vm
     *            virtual machine.
     * @param plan
     *            deployment plan that tells you where it's being deployed to.
     * @param avoid
     *            avoid these data centers, pods, clusters, or hosts.
     * @return DeployDestination for that virtual machine.
     */
    List<Long> orderClusters(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid)
            throws InsufficientServerCapacityException;

    PlannerResourceUsage getResourceUsage();

}


Thus the current Planners will be refactored to just return the ordered list of clusters. DPM will execute the rest of the logic:

- Iterate over the cluster list

- For each cluster, call hostAllocators to get a list of suitable hosts

- For each cluster, call storagePoolAllocators to get a list of suitable pools

- Find a potential DeployDestination that consists of host-storagepool to deploy the VM considering factors like: host-storage pool linkage, planner host reservation.

This means that the current API in DeploymentPlanner interace will be deprecated for future usage.

public interface DeploymentPlanner extends Adapter {

    @Deprecated
    DeployDestination plan(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException;

API Changes

  1. listDeploymentPlanners Admin API - This will be a new API that will let Admin list the available set of deployment planners.
  2. createServiceOffering API changes - Following new field will be added to this API
    1. deploymentplanner - String value (optional parameter)

DB Changes

  1. Additional column to service_offering:
    ALTER TABLE `cloud`.`service_offering` ADD COLUMN `deployment_planner` varchar(255) COMMENT 'Planner heuristics used to deploy a VM of this offering; if null global config vm.deployment.planner is used';
  2. A new table to store planner reservations. Following are some columns needed:
    CREATE TABLE `cloud`.`op_host_planner_reservation` (
      `id` bigint unsigned NOT NULL auto_increment,
      `data_center_id` bigint unsigned NOT NULL,
      `pod_id` bigint unsigned,
      `cluster_id` bigint unsigned,
      `host_id` bigint unsigned,
      `resource_usage` varchar(255) COMMENT 'Shared(between planners) Vs Dedicated (exclusive usage to a planner)',
      PRIMARY KEY  (`id`),
      INDEX `i_op_host_planner_reservation__host_resource_usage`(`host_id`, `resource_usage`),
      CONSTRAINT `fk_planner_reservation__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
      CONSTRAINT `fk_planner_reservation__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `cloud`.`data_center`(`id`) ON DELETE CASCADE,
      CONSTRAINT `fk_planner_reservation__pod_id` FOREIGN KEY (`pod_id`) REFERENCES `cloud`.`host_pod_ref`(`id`) ON DELETE CASCADE,
      CONSTRAINT `fk_planner_reservation__cluster_id` FOREIGN KEY (`cluster_id`) REFERENCES `cloud`.`cluster`(`id`) ON DELETE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  3. Global config variable to choose a planner if no planner is selected in the ServiceOffering
    INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'vm.deployment.planner', 'FirstFitPlanner', '[''FirstFitPlanner'', ''UserDispersingPlanner'', ''UserConcentratedPodPlanner'']: DeploymentPlanner heuristic that will be used for VM deployment.');
  4. INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'host.reservation.release.period', '300000', 'The interval in milliseconds between host reservation release checks');

UI Changes

Following UI changes are needed:

Add a field 'deployment planner' to the createServiceOffering UI. The parameter is optional. The value should be accepted using an empty input box.

  • No labels