Application Packaging Standard

Last updated 18-Mar-2019

Provisioning Logic

In this section, you will modify the vpses.php script since it is responsible for all operations with servers in the application.

Required Updates

Following the outlined Design Review, we need to edit three methods:

  • provision() - when provisioning a new server, it must send a notification with type activity and status ready, if a VPS is required, or inProgress, if a VM is required.
  • provisionAsync() - it processes an async request and modifies the notification linked with the VM.
  • unprovision() - when removing a server, it must remove the existing notification and send a new one of type warning.
../../../../_images/notification-step-design.png ../../../../_images/notification-step-provision-b.png ../../../../_images/notification-step-deploy.png ../../../../_images/notification-step-provisioning.png

Continue Your Demo Project

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

Server Properties

The provisioning logic scripts mentioned above are able to work with a certain notification linked with a VPS. For this purpose, make the notification ID stored as one of VPS properties. In the vps class, declare the notificationId property:

/**
 * @type(string)
 * @title("Notification ID")
 */
public $notificationId;

Provision Method

Update the provision method as follows.

  1. Prepare a connection with the notification manager and define interface elements.

    • Get an instance of the notification manager

      $notificationManager = \APS\NotificationManager::getInstance();
      
    • Get ready the account APS ID needed for the notification message. For this purpose, use the VPS-to-context relationship and the context-to-account relationship in a chain.

      $accountId = $this->context->account->aps->id;
      
  2. Define the notification message corresponding to the Message structure in the notification manager. In accordance with Design Review, use two modifications of it.

    • Create a notification message for the case, when a VPS (without OS kernel) is requested.

      $notification = new \APS\Notification;
      $notification->message = new \APS\NotificationMessage("VPS Creation");
      $notification->details = new \APS\NotificationMessage(
          "VPS __name__ is provisioned",
          array("name" => $this->name)
      );
      $notification->accountId = $accountId;
      $notification->status = \APS\Notification::ACTIVITY_READY;
      $notification->packageId = $this->aps->package->id;
      $notification->link = new \APS\NotificationLink(
          "/v/aps/samples/async1pn/servers",                      // Main link
          "/v/aps/samples/async1pn/server-edit/r/".$this->aps->id, // Link more
          "View or edit VPS"                                       // Link more text
      );
      
    • Modify the notification message for the case, when a VM (with OS kernel) is requested. Use one more if($this->hardware->VM) clause.

      if($this->hardware->VM ) {
          $this->state = "Creating"; // VM state is intermediate
      
          // Edit the notification message
          $notification->message->message = "VM Creation";
          $notification->details->message = "Provisioning of VM __name__ is started";
          $notification->status = \APS\Notification::ACTIVITY_IN_PROGRESS;
          $notification->link->linkMore = "/v/aps/samples/async1pn/servers";
          $notification->link->linkMoreText->message = "View Servers";
      }
      
  3. Send the new notification and save the notification ID.

    // Send the notification
    $notificationResponse = $notificationManager->sendNotification($notification);
    
    // Store the notification ID as the VPS property to update or remove it in other operations
    $this->notificationId = $notificationResponse->id;
    
  4. Make sure the exception for starting the async process is thrown at the very end of the provision method.

    if ($this->hardware->VM ) {
       //Require async operation:
       throw new \Rest\Accepted($this, "Creating VM", 15); // Returns code "202 Accepted"
    } else {
       // Simulate the end of async provisioning to show correct status in UI
       $this->retry = 5;
    }
    

ProvisionAsync Method

In accordance with Design Review, this method should only modify the existing notification bound to the VM that is under processing. For this reason, there is no need to define the whole notification message.

  1. Prepare a connection with the notification manager and define interface elements the same way you did it in the provision method.

    // Get an instance of the Notification Manager:
    $notificationManager = \APS\NotificationManager::getInstance();
    
    // Get ready account APS ID needed for the notification structure.
    $accountId = $this->context->account->aps->id;
    
    // Increment the retry counter
    $this->retry +=1;
    
  2. Get ready two modifications of the notification.

    • The async provisioning is not finished yet (retry < 5):

      $notification = new \APS\Notification;
      $notification->message = new \APS\NotificationMessage("VM Creation");
      $notification->details = new \APS\NotificationMessage(
          "Provisioning of VM __name__ is in progress",
          array("name" => $this->name)
      );
      $notification->fullDetails = new \APS\NotificationMessage(
          "__percent__ % of the Virtual Machine provisioning is completed",
          array("percent" => $this->retry * 20)
      );
      $notification->link = new \APS\NotificationLink(
          "",
          "/v/aps/samples/async1pn/servers",
          "View Servers"
      );
      
    • The async provisioning is finished (retry >= 5):

      if ($this->retry >= 5) {
         $this->state = "Stopped";  // Finish the Async operation - return 200 OK to APSC
         $notification->details->message = "Provisioning of VM __name__ is completed";
         $notification->status = \APS\Notification::ACTIVITY_READY;
         $notification->link->linkMore="/v/aps/samples/async1pn/server-edit/r/".$this->aps->id;
         $notification->link->linkMoreText->message = "View or edit VM";
      }
      
  3. Send the notification update request through the PUT operation.

    if (isset($this->notificationId)) {
         $notificationResponce = $notificationManager->editNotification(
             $this->notificationId,
             $notification
    );}
    
  4. Make sure the exception for continuing the async process is thrown at the very end of the provisionAsync method.

    if ($this->retry < 5) {
       // Require the next async retry
       throw new \Rest\Accepted($this, "Creating VM", 15); // Return code "202 Accepted"
    }
    

Unprovision Method

As follows from Design Review, in the unprovision() method, you need to remove the notification along with the server whose removal is requested and then send a warning notification, either with status upcoming or existing. The condition is based on the number of servers remained, either non-zero or zero.

  1. Prepare a connection with the notification manager and define interface elements the same way you did it in the provision method.

    $accountId = $this->context->account->aps->id;
    
    // Get an instance of the Notification Manager:
    $notificationManager = \APS\NotificationManager::getInstance();
    
  2. Get ready the notification message for the two cases.

    • At least one server remains after the removal:

      $notification = new \APS\Notification;
      $notification->message = new \APS\NotificationMessage("Server Removal");
      $notification->details = new \APS\NotificationMessage(
          "Server __name__ is removed",
          array("name" => $this->name)
      );
      $notification->type = \APS\Notification::TYPE_WARNING;
      $notification->accountId = $accountId;
      $notification->status = \APS\Notification::WARNING_UPCOMING;
      $notification->packageId = $this->aps->package->id;
      $notification->link = new \APS\NotificationLink(
          "/v/aps/samples/async1pn/servers",
          "/v/aps/samples/async1pn/servers",
          "View Servers"
      );
      
    • Removal of the last server:

      // Get a list of VPSEs to count the remained ones
      $apsc = \APS\Request::getController();
      $vpses = $apsc->getResources(
          'implementing(http://aps-standard.org/samples/async1pn/vps/1.0)'
      );
      
      // Removing the last server of the customer?
      if (count($vpses) <= 1) {
         $notification->details->message = "The last server __name__ is removed";
         $notification->status = \APS\Notification::WARNING_EXISTING;
      }
      
  3. Remove the existing notification and send the new one.

    // If Notification Manager is available, remove the notification
    if (isset($this->notificationId)) {
    
       // Remove the stored Notification
       $notificationManager->deleteNotification($this->notificationId);
       unset($this->notificationId);
    
       // Send the new notification
       $notificationManager->sendNotification($notification);
    }
    

Conclusion

This completes modification of the vpses.php file, which is a part of the provisioning logic. You can compare the added code with the contents in the respective file inside the sample package.