Provisioning Logic

The most important in this project is to develop the provisioning logic that will compute counters on demand.

../../../../_images/counters-step-intro.png ../../../../_images/counters-step-provision-b.png ../../../../_images/counters-step-presentation.png ../../../../_images/counters-step-deploy.png ../../../../_images/counters-step-provisioning.png

Resource Model

We do not need to add any new types to those used in the input package, and the project still contains three APS types. We are going to compute CPU, RAM, and disk usage. Therefore, the respective properties and functions must be added to the VPS provisioning logic.

GraphViz

Since the singular subscription service type is counters/context in this project, we should define the counters inside that type.

The application and the business support system (BSS) part of the platform differs additive from non-additive counters. Using those counters, BSS can charge customers for resource consumption at the end of every billing period. The price is set for:

  • Non-additive counter - average of the resource counter over the billing period. In this project, the disk space measured in GB is such a counter.

  • Additive counter - final value of the resource counter at the end of the billing period. In this project, the CPU cores measured in item-hour and memory space measured in MB-hour are such resources.

Non-Additive Counters

Let us consider a primitive algorithm to count resource consumption with the help of the non-additive counter, which is the disk space in the current scenario:

  • The current resource usage is stored in the APS controller.

    Note

    In most implementations, the application itself determines actual resource usage on the application cloud side using its own algorithm.

  • The following operations can change the resource usage:

    • Provision (CREATE) new server (VPS) since it allocates some disk space to the VPS

    • Update (PUT) a VPS since it can change the amount of disk space allocated to the VPS

    • Remove (DELETE) a VPS since it releases the disk space allocated earlier to the VPS

    For simplicity, in this demo, we do not have a cloud application that tracks those operations. Instead, the APS application connector gets the resource usage from the APS database and saves the updated counters in the same database.

  • The platform periodically polls resource counters by calling the retrieve operation on the respective resource. In the resource model, the management context is such a resource that must have a definition of the retrieve operation. The latter will call the APS controller for resource usage per VPS and updates the total resource usage per customer.

Additive Counters

The additive resources, which are CPU cores and memory space, require the application to track resource changes in time and accumulate the resource usage.

Note

  1. Normally, the application computes its resource usage and returns its resource counters by request.

2. In this demo project, for simplicity, the APS connector computes the resource usage by a request from the platform or from the custom UI.

3. The primitive resource usage pattern implies that the integrated parameter (CPU cores or memory space) is permanent until one of the provisioning operation (create, update, or delete) changes them.

The standard create, update, and delete operations as well as the custom start and stop operations change the rate of the total resource increase. So, each of those operations will call the APS controller to update the accumulated counter usage. For this purpose, the management context resource should have a method, for example, resourceCounting(), that other methods will call.

../../../../_images/resourceCounting.png

The retrieve operation, as mentioned earlier, does not affect a counter rate and just collects the latest accumulated resource usage for the system.

In addition to the counter property usage that shows the latest accumulated value of the resource usage, the algorithm introduced by the above diagram also uses some auxiliary variables:

  • time1 - the time of the last update of the resource counter

  • time - the current time

  • value1 - the rate of the past period, for example, CPU cores (items) or RAM (MB)

  • value - the rate of the next period

  • usage1 - the counter usage value in the last update, for example, CPU usage (item-hour) or memory usage (MB-hour)

Service Overview

In this project, we neither add new services nor modify any relations. Thus, the list of services and relations remains the same as we used in the resource model of the previous Generic Services project.

Type Name

Type ID

Relation

Relation parameters

Cloud

http://aps-standard.org/samples/counters/cloud/1.0

contexts

Collection-Optional

Context

http://aps-standard.org/samples/counters/context/1.0

cloud
vpses
Singular-Required
Collection-Optional

VPS

http://aps-standard.org/samples/counters/vps/1.0

context

Singular-Required

To implement the resource model and resource counting pattern, update the provisioning logic as follows.

  1. To account resource usage in the subscription, add the respective counters to the management context APS type. The latter is linked with all VPSes consuming resources. This allows the contexts service to poll the VPSes for the actual resource usage.

  2. In the management context, define a resource counting method resourceCounting() to implement the resource counting pattern.

  3. In each operation that affects the accumulation rate of resource consumption, add the call of the resourceCounting() method to accumulate resource usage for the previous period.

Continue Your Demo Project

This section continues the demo project started in the previous step.

Declare Resource Counters

In the scripts/contexts.php file, use the APS counter structure defined in the standard Resource APS type to declare the resource counters as follows:

/**
 * @type("http://aps-standard.org/types/core/resource/1.0#Counter")
 * @description("Total disk space usage, GB")
 * @unit("gb")
 */
public $diskUsageTotal;

/**
 * @type("http://aps-standard.org/types/core/resource/1.0#Counter")
 * @description("Total CPU usage, CPUcore-hour")
 * @unit("item-h")
 */
public $cpuUsageTotal;

/**
 * @type("http://aps-standard.org/types/core/resource/1.0#Counter")
 * @description("Total memory usage, MB-hour")
 * @unit("mb-h")
 */
public $memoryUsageTotal;

Each counter declaration contains APS type, description, unit of measure, and the variable name.

Since the application must update the counters only when the retrieve operation is called by the periodic resource synchronization process, the application needs some auxiliary properties to accumulate additive resources in the period between the retrieve polls. For this purpose, add two auxiliary accumulators for the two additive counters:

/**
* @type("integer")
* @description("Accumulates CPU usage in the period between the retrieve polls")
 * @unit("item-h")
 */
public $cpuAccumulator;

/**
* @type("integer")
* @description("Accumulates memory usage in the period between the retrieve polls")
 * @unit("mb-h")
 */
public $memoryAccumulator;

Initialize Variables

The platform starts polling counters since the time the resource with these counters is provisioned. That is why, the provision() method in the scripts/contexts.php file must initialize the counters in accordance with the resource counting pattern.

Update the context class as follows.

  1. Declare the auxiliary time1 property required by the counting algorithm:

    /**
    * @type("integer")
    * @description("Time stamp of the last resource usage counting")
    */
    public $time1;
    
  2. Define the provision method and initialize the variables used to accumulate resource usage:

    public function provision() {
       $this->time1 = time();
       $this->cpuUsageTotal->usage = 0;
       $this->memoryUsageTotal->usage = 0;
       $this->diskUsageTotal->usage = 0;
       $this->cpuAccumulator = 0;
       $this->memoryAccumulator = 0;
    }
    

Retrieve Resource

Once the management context with its counters is provisioned in a subscription, the platform will periodically poll the counters by calling the retrieve() method of the management context service. Thus, define this method in scripts/contexts.php.

  1. Build the typical function structure:

    public function retrieve() {
       ## Initialize the local variables
    
       ## Collect resource usage from all VPSes
       foreach ($this->vpses as $vps) {
    
       }
    
       ## Update the APS resource counters
    
    }
    
  2. Inside the function, initialize the local variables:

    $currenttime = time();
    $timedelta = ($currenttime - $this->time1) / 3600;      // Elapsed time in hours
    $this->time1 = $currenttime;
    
    $cpuRate = 0;
    $ramRate = 0;
    $cpuUsage = $this->cpuAccumulator;
    $ramUsage = $this->memoryAccumulator;
    $diskUsage = 0;
    
  3. Reset the accumulators and then save them and the current time in the APS database:

    $this->cpuAccumulator = 0;
    $this->memoryAccumulator = 0;
    $apsc = \APS\Request::getController();
    $apsc->updateResource($this);
    
  4. Collect resource usage by polling each VPS through the vpses relationship collection:

    foreach ($this->vpses as $vps) {
       if ($vps->state == 'Running') {
          $cpuRate += $vps->hardware->CPU->number;
          $ramRate += $vps->hardware->memory;
       }
       $diskUsage += $vps->hardware->diskspace;
    }
    
    ## Delta during the period between the retrieve polls
    $cpuUsage += floor($cpuRate * $timeDelta);
    $ramUsage += floor($ramRate * $timeDelta);
    

    The above code collects additive resources (CPU and RAM) only from the running VPSes, whereas the non-additive resource Disk space is counted regardless of the VPS state. The code rounds down the additive resources.

  5. Update the APS counters in the context resource:

    ## Update the APS resource counters
    $this->cpuUsageTotal->usage += $cpuUsage;
    $this->memoryUsageTotal->usage += $ramUsage;
    $this->diskUsageTotal->usage = $diskUsage;
    

Count Resources on Demand

Since the retrieve() method does not belong to a custom APS operation, but rather is a method used by the platform, the context type must also have a custom operation that other custom methods can call to accumulate additive resources in accordance with the earlier considered algorithm.

The internal code of this custom method in some parts is similar to the internals of the retrieve() method:

/**
* @verb(GET)
* @path("/resourceCounting")
*/
public function resourceCounting() {
   $currentTime = time();
   $timeDelta = ($currentTime - $this->time1) / 3600; // Elapsed time in hours
   $this->time1 = $currentTime;

   $cpuRate = 0;
   $ramRate = 0;
   foreach ($this->vpses as $vps) {
      if ($vps->state == 'Running') {
         $cpuRate += $vps->hardware->CPU->number;
         $ramRate += $vps->hardware->memory;
      }
   }
   $this->cpuAccumulator += floor($cpuRate * $timeDelta);  // Additive
   $this->memoryAccumulator += floor($ramRate * $timeDelta);  // Additive
   $apsc = \APS\Request::getController();
   $apsc->updateResource($this);
}

After collecting the counters, the method saves them in the APS database.

Note

In the standard APS retrieve operation, there is no need to make the APS controller update a counter by calling updateResource since the APS controller does it automatically. In custom operations, you have to call updateResource explicitly.

This completes development of the scripts/contexts.php file. You can compare it with the similar file in the sample package.

Demand Resource Counting

The vps resources defined by the scripts/vpses.php script do not use APS counters. However, the provision, configure, and unprovision operations over those resources influence the counters. In accordance with the algorithm, each of those operations as well as the start and stop operations must call the resourceCounting method to collect resource usage before the resource values are changed.

In the scripts/vpses.php file, ensure the above-mentioned operations are defined as follows.

public function provision() {
       $this->context->resourceCounting();
}

public function unprovision() {
       $this->context->resourceCounting();
}

public function configure($new) {
       $this->context->resourceCounting();
       parent::configure($new);
}

// Custom functions called on pressing start/stop buttons in custom UI:
/**
* @verb(GET)
* @path("/start")
*/
public function start() {
       $this->context->resourceCounting();     // Accumulate resource usage

       $this->state = 'Running';
       $apsc = \APS\Request::getController();
       $apsc->updateResource($this);
}

/**
* @verb(GET)
* @path("/stop")
*/
public function stop() {
       $this->context->resourceCounting();     // Accumulate resource usage

       $this->state = 'Stopped';
       $apsc = \APS\Request::getController();
       $apsc->updateResource($this);
}

Conclusion

This completes development of the provisioning logic that is ready now to use APS counters for computing the usage of various additive and non-additive application resources.

Note

The project files you have created are similar to the respective files in the sample package.