The most important in this project is to develop the provisioning logic that will compute counters on demand.
In this document:
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.
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:
GB
is such a counter.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:
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.
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
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.
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 countertime
- the current timevalue1
- the rate of the past period, for example, CPU cores (items) or RAM (MB)value
- the rate of the next periodusage1
- the counter usage
value in the last update, for example, CPU usage (item-hour) or memory usage (MB-hour)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.
contexts
service to poll the VPSes
for the actual resource usage.resourceCounting()
to implement the resource counting pattern.resourceCounting()
method
to accumulate resource usage for the previous period.This section continues the demo project started in the previous step.
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;
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.
Declare the auxiliary time1
property required by the counting algorithm:
/**
* @type("integer")
* @description("Time stamp of the last resource usage counting")
*/
public $time1;
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;
}
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
.
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
}
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;
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);
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.
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;
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
.
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);
}
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
.