According to the Resource Model, you should define the new APS type,
its relationship with the existing context
APS type,
and the event processing logic of the respective service.
In this document:
In this project, you have added the event
APS type and the events
service.
The single resource that will be provisioned by the service
in a subscription must link with the context
resource within the same subscription.
This extends the list of APS types in the application.
APS Type | APS ID | Relationship | Attributes |
---|---|---|---|
Cloud | http://aps-standard.org/samples/event-mgmt/cloud/1.0 | contexts | Collection-Optional |
Offer | http://aps-standard.org/samples/event-mgmt/offer/1.0 | cloud
vpses
|
Singular-Required
Collection-Optional
|
Context | http://aps-standard.org/samples/event-mgmt/context/1.0 | cloud
vpses
event
|
Singular-Required
Collection-Optional
Singular-Optional
|
VPS | http://aps-standard.org/samples/event-mgmt/vps/1.0 | context
offer
user
|
Singular-Required
Singular-Required
Singular-Required
|
Event | http://aps-standard.org/samples/event-mgmt/event/1.0 | context | Singular-Required |
As follows from the table, you do not need to touch clouds.php
, offers.php
, and vpses.php
in this step.
The provisioning logic should be modified as follows:
contexts.php
file, we need to set a relationship with the event
type.events.php
file must be developed. It must demonstrate how to subscribe to events
of different types and process event notifications.events
service must record event notifications in its internal log and
by requests from UI provide the log contents and flush the event log.Continue the demo project from the previous step.
We use a simplified event processing - just adding the received notifications to the log file
that will be scripts/eventlog.txt
by default.
A new scripts/logger.php
file defines the Logging
class with the following
public functions:
logfile($path)
sets the actual path to the log file.logwrite($message)
adds a message to the log file.logclose()
closes the log file.flushlog()
empties the log file.<?php
/**
* Logging class:
* - contains "logfile", "logwrite", "flushlog", and "logclose" public methods
* - "logfile" sets path and name of log file
* - "logwrite" writes message to the log file (and implicitly opens log file)
* - "logclose" closes log file
* - "flushlog" returns the event log content and flushes the log
* - first call of the "logwrite" method will open the log file implicitly
* - a message is written with the following format: "[d/M/Y:H:i:s] (script name) message"
*/
class Logging {
## Declare log file and file pointer as private properties
private $log_file = './eventlog.txt';
private $fp;
## Set log file (path and name)
public function logfile($path) {
if (strlen($path) > 0) {
$this->log_file = $path;
}
}
## Open log file (private method)
private function logopen() {
#### Open log file for writing only and place file pointer at the end of the file.
#### If the file does not exist, try to create it.
$this->fp = fopen($this->log_file, 'a+') or exit("Can't open $logfile!");
}
## Close log file (it's always a good idea to close a file when you're done with it)
public function logclose() {
fclose($this->fp);
}
## Write message to the log file
public function logwrite($message) {
#### If file pointer doesn't exist, then open log file
if (!is_resource($this->fp)) {
$this->logopen();
}
#### Define script name
$script_name = pathinfo($_SERVER['PHP_SELF'], PATHINFO_FILENAME);
#### Define current time and suppress E_WARNING if using the system TZ settings
#### (don't forget to set the INI setting date.timezone)
$time = @date('[d/M/Y:H:i:s e]');
#### Write current time, script name and message to the log file
fwrite($this->fp, "$time ($script_name) $message\n");
}
public function flushlog() {
#### If the log has not been created, return empty contents
if (! file_exists($this->log_file))
return "";
$fp = fopen($this->log_file, 'r+');
if (!$fp) return "";
$content = file_get_contents($this->log_file);
ftruncate($fp, 0);
return $content;
}
}
?>
Event monitoring logic will use the defined class and its methods to process event notifications.
In the scripts/contexts.php
, add a link with the event
type:
/**
* @link("http://aps-standard.org/samples/event-mgmt/event/1.0")
*/
public $event;
In a subscription, there will be one event
resource linked with the management context
.
Define the APS type and the service (resource factory) in the scripts/events.php
file as follows:
Create the script structure:
<?php
# Class Logging will be used for logging event notifications
require "logger.php";
require "aps/2/runtime.php";
/**
* Class event
* @type("http://aps-standard.org/samples/event-mgmt/event/1.0")
* @implements("http://aps-standard.org/types/core/subscription/service/1.0”)
*/
class event extends \APS\ResourceBase {
## Require a link to the management context
## Define a Logger function that will log a new Event Notification as a message
## Define a function that returns the list of Notifications logged by the service
## Subscribe to Events during the provisioning process using APS PHP runtime:
public function provision() {
#### Create several event subscription objects
#### Connect to the APS controller
#### Subscribe to possible events
}
## For each type of Event Notifications, define a handler
}
?>
In the above code, we are going to re-define the inherited provision()
method. It is called only once, when
the event
resource is provisioned from the subscription. During the provisioning, it will subscribe the resource
to various event sources.
Require a link to the management context:
/**
* @link("http://aps-standard.org/samples/event-mgmt/context/1.0")
* @required
*/
public $context;
Define a custom public method readNotifications()
that provides the list of event notifications logged by the service
and empties the log after that. It uses the Logging
class defined in the logger.php
file.
The method will be called from the custom UI to present a list of logged event notifications on the screen.
/**
* @verb(GET)
* @path("/readNotifications")
* @return(string)
*/
public function readNotifications() {
$log = new Logging();
$log->logfile('./'.$this->aps->id.'.log');
return $log->flushlog();
}
Define the private Logger()
function used by event handlers to log event notifications.
It calls the Logging
class methods defined in the logger.php
file:
function logger($message){
$requester=$_SERVER['REMOTE_ADDR'];
$log = new Logging();
$log->logfile('./'.$this->aps->id.'.log');
$log->logwrite($requester.":".$message);
$log->logclose();
}
In the provision()
function, create event subscription objects.
In each event subscription, specify the event type and event handler.
Events on operations with VPSes - creation, removal, change of properties, linking, and unlinking:
$subVPSavailable = new \APS\EventSubscription(\APS\EventSubscription::Available,
"onVPSavailable");
$subVPSremove = new \APS\EventSubscription(\APS\EventSubscription::Removed,
"onVPSremove");
$subVPSchange = new \APS\EventSubscription(\APS\EventSubscription::Changed,
"onVPSchange");
$subVPSofferLink = new \APS\EventSubscription(\APS\EventSubscription::Linked,
"onVPSofferLink");
$subVPSofferUnlink = new \APS\EventSubscription(\APS\EventSubscription::Unlinked,
"onVPSofferUnlink");
$subVPSuserLink = new \APS\EventSubscription(\APS\EventSubscription::Linked,
"onVPSuserLink");
$subVPSuserUnlink = new \APS\EventSubscription(\APS\EventSubscription::Unlinked,
"onVPSuserUnlink");
Events on creation and removal of customer’s domains:
$subDomainAvailable = new \APS\EventSubscription(\APS\EventSubscription::Available,
"onDomainAvailable");
$subDomainRemove = new \APS\EventSubscription(\APS\EventSubscription::Removed,
"onDomainRemove");
Events on creation and removal of customer’s service users:
$subUserAvailable = new \APS\EventSubscription(\APS\EventSubscription::Available,
"onUserAvailable");
$subUserRemove = new \APS\EventSubscription(\APS\EventSubscription::Removed,
"onUserRemove");
Connect to the APS controller:
$apsc = \APS\Request::getController();
if ($apsc == null) {
error_log("apsc is null");
}
Activate all event subscriptions declared earlier. In each event subscription, specify the event type.
For linked
and unlinked
events, also specify the relation name.
Events on operations with VPSes:
$subVPSavailable->source->type="http://aps-standard.org/samples/event-mgmt/vps/1.0";
$apsc->subscribe($this, $subVPSavailable);
$subVPSremove->source->type="http://aps-standard.org/samples/event-mgmt/vps/1.0";
$apsc->subscribe($this, $subVPSremove);
$subVPSchange->source->type="http://aps-standard.org/samples/event-mgmt/vps/1.0";
$apsc->subscribe($this, $subVPSchange);
$subVPSofferLink->source->type="http://aps-standard.org/samples/event-mgmt/vps/1.0";
$subVPSofferLink->relation='offer';
$apsc->subscribe($this, $subVPSofferLink);
$subVPSofferUnlink->source->type="http://aps-standard.org/samples/event-mgmt/vps/1.0";
$subVPSofferUnlink->relation='offer';
$apsc->subscribe($this, $subVPSofferUnlink);
$subVPSuserLink->source->type="http://aps-standard.org/samples/event-mgmt/vps/1.0";
$subVPSuserLink->relation='user';
$apsc->subscribe($this, $subVPSuserLink);
$subVPSuserUnlink->source->type="http://aps-standard.org/samples/event-mgmt/vps/1.0";
$subVPSuserUnlink->relation='user';
$apsc->subscribe($this, $subVPSuserUnlink);
Events on creation and removal of customer’s domains defined in the platform APS type PAHostedDomain:
$subDomainAvailable->source->type="http://parallels.com/aps/types/pa/dns/zone/1.0";
$apsc->subscribe($this, $subDomainAvailable);
$subDomainRemove->source->type="http://parallels.com/aps/types/pa/dns/zone/1.0";
$apsc->subscribe($this, $subDomainRemove);
Events on creation and removal of customer’s service users defined in the platform APS type PAServiceUser:
$subUserAvailable->source->type="http://parallels.com/aps/types/pa/service-user/1.1";
$apsc->subscribe($this, $subUserAvailable);
$subUserRemove->source->type="http://parallels.com/aps/types/pa/service-user/1.1";
$apsc->subscribe($this, $subUserRemove);
For each type of event notifications, define a handler that stores event notifications in the log.
Notifications sent in the message body must comply with the notification
structure defined in the
standard APS type Resource.
Handlers use the private logger($message)
function defined earlier in the same event
class.
New VPS is available:
/**
* @verb(POST)
* @path("/onVPSavailable")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onVPSavailable($notification) {
$this->logger("VPS created: ".json_format($notification));
}
A VPS is removed:
/**
* @verb(POST)
* @path("/onVPSremove")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onVPSremove($notification) {
$this->logger("VPS removed: ".json_format($notification));
}
A VPS is linked or re-linked to an offer:
/**
* @verb(POST)
* @path("/onVPSofferLink")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onVPSofferLink($notification) {
$this->logger("New offer Linked: ".json_format($notification));
}
A VPS is unlinked from its offer:
/**
* @verb(POST)
* @path("/onVPSofferUnlink")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onVPSofferUnlink($notification) {
$this->logger("Offer Unlinked: ".json_format($notification));
}
A VPS is linked or re-linked to a service user:
/**
* @verb(POST)
* @path("/onVPSuserLink")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onVPSuserLink($notification) {
$this->logger("New user Linked: ".json_format($notification));
}
A VPS is unlinked from its service user:
/**
* @verb(POST)
* @path("/onVPSuserUnlink")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onVPSuserUnlink($notification) {
$this->logger("User UnLinked: ".json_format($notification));
}
VPS properties are changed:
/**
* @verb(POST)
* @path("/onVPSchange")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onVPSchange($notification) {
$this->logger("VPS properties changed: ".json_format($notification));
}
A new hosted domain is available:
/**
* @verb(POST)
* @path("/onDomainAvailable")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onDomainAvailable($notification) {
$this->logger("New Domain available: ".json_format($notification));
}
A hosted domain is removed:
/**
* @verb(POST)
* @path("/onDomainRemove")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onDomainRemove($notification) {
$this->logger("Domain removed: ".json_format($notification));
}
A new service user is available:
/**
* @verb(POST)
* @path("/onUserAvailable")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onUserAvailable($notification) {
$this->logger("New User available: ".json_format($notification));
}
A service user is removed:
/**
* @verb(POST)
* @path("/onUserRemove")
* @param("http://aps-standard.org/types/core/resource/1.0#Notification",body)
*/
public function onUserRemove($notification) {
$this->logger("User removed: ".json_format($notification));
}
Keynotes:
event
type will requires a singular link with a resource of the context
type.provision()
function is substantially extended with the requests for subscribing to various event types.
We use three groups of sources: VPSes, domains, and service users.
To get subscribed, a number of steps are needed:EventSubscription
class (defined in APS PHP runtime)
with declaration of the event handlers. For example,
the event subscription $subVPSofferLink
object with the onVPSofferLink
handler is created.http://aps-standard.org/samples/event-mgmt/vps/1.0
.
For the linked
and unlinked
event types, we also define the relation name, for example, offer
.getController()
function.$apsc->subscribe($this,$subVPSofferLink)
.onVPSofferLink($notification)
function will process POST requests on the “/onVPSofferLink” path.
The handler will expect receiving JSON objects in the message body as defined in
the http://aps-standard.org/types/core/resource/1.0#Notification
structure
of the standard APS type Resource.
The message processing is pretty simple - notifications are stored in the log file.readNotifications()
function that provides the log file contents on requests.
It flushes the log file after that. The function is needed for integration with the presentation layer.You have designed and developed the provisioning logic for the demo application. The new APS type and the respective service are able to subscribe to events and process event notifications in accordance with the scenario.
The files you have created are similar to the respective files in the
sample package
.