In this article, we’ll learn how to implement the App’s deployment.

To deploy an App successfully, you need to implement the following 4 methods:

  1. Deploy creates the App’s VM instance.
  2. PowerOn spins up the VM.
  3. remote_refresh_ip updates the deployed App’s IP address.
  4. GetVmDetails gets information about the VM itself, its operating system, specifications and networking information.

These methods are executed in the above order during the deployment of an App in the sandbox (either automatically as part of the default sandbox setup script that runs when reserving a sandbox or manually by the user after adding an App to an active sandbox). Once the App is deployed, these methods can be run as individual commands from the deployed App’s commands pane, with the exception of the Deploy command which is no longer needed once the App is deployed..

Deploy method

Creates the App’s VM instance.

Signature

The deploy method accepts three inputs: context, request, and cancellation_context.

src/driver.py view raw
def Deploy(self, context, request, cancellation_context=None):

Inputs

context

context: context is a ResourceCommandContext object that contains:

  1. connectivity - CloudShell server connectivity data for authentication with CloudShell Automation API
  2. resource - resource configuration settings entered when creating the Cloud Provider resource in the Inventory dashboard
  3. reservation - current reservation details
  4. connectors – details of any visual connectors between the Cloud Provider App and other endpoints in the sandbox
cloudshell/shell/core/driver_context.py view raw
class ResourceCommandContext:
    def __init__(self, connectivity, resource, reservation, connectors):
        self.connectivity = connectivity  # Connectivity details that can help connect to the APIs
        """:type : ConnectivityContext"""
        self.resource = resource  # The details of the resource using the driver
        """:type : ResourceContextDetails"""
        self.reservation = reservation  # The details of the reservation
        """:type : ReservationContextDetails"""
        self.connectors = connectors  # The list of visual connectors and routes that are connected to the resource (the resource will be considered as the source end point)
        """:type : list[Connector]"""

Request

Request object that contains the resource deployment path and deployed App configuration (in the App template’s App Resource page).

cancellation_context

CloudShell supports the canceling of App command executions.

cloudshell/shell/core/driver_context.py view raw
def __init__(self):
    self.is_cancelled = False
    """:type : bool"""

To allow the cancellation of a command on the Cloud Provider’s Apps, we need to:

  1. Check for cancellation before each operation. If cancelled, delete cloud objects created by operation.
  2. Return the appropriate result.

Usage example

src/heavenly_cloud_service_wrapper.py view raw
if cancellation_context.is_cancelled:
      # rollback what we created for current executing command then raise exception
      # HeavenlyCloudService.rollback()
      raise Exception('Operation cancelled')

Output

DriverResponse object that contains a list of action results.

Error handling

If App deployment fails, return a “success false” action result.

Deploy method implementation

The deploy method should perform the following steps:

  1. Retrieve the cloud provider resource’s connection credentials.
  2. Retrieve the Deploy action.
  3. Call the Deploy logic of the selected deployment type.
  4. (Steps 4 - 8 are performed within the deploy logic) Generate a unique name for the App. For example, “My-App_968e-a950”. Deployed Apps are classified as resources in CloudShell and therefore must have a unique name.
  5. Create a VM instance using the deployment path attributes (the HeavenlyCloud service represents your custom cloud SDK).
  6. If VM deployment is successful:
    • Collect VM details (operating system, specifications, networking information).
    • Optionally, override App resource attribute values. For example, if we generate a unique password for each VM instance, we will also want to update this password in the Password attribute on the Deployed App Resource for future use (to allow the sandbox end-user to connect to the VM).
    • If needed, add additional data to the action result. This key-value data will be available from all API resource queries. It can be useful for implementing custom logic during the lifecycle of the sandbox. Example.
  7. If VM deployment fails, return a “fail” result.
  8. Return DeployAppResult.
  9. Return DriverResponse.

Note that the links in the above workflow pertain to a driver of an L2 implementation. However, the only difference between L2 and L3 driver implementations is that L2 implements ApplyConnectivityChanges while L3 uses the PrepareSandboxInfra and CleanSandboxInfra methods.

DeployAppResult JSON example

Click here

{
  "actionId": "aac7cc0c-a215-4aee-8fc1-f79.3.034423",
  "deployedAppAdditionalData": {},
  "deployedAppAddress": "192.168.0.5",
  "deployedAppAttributes": [
    {
      "attributeName": "Password",
      "attributeValue": "123456"
    },
    {
      "attributeName": "User",
      "attributeValue": "super user"
    }
  ],
  "errorMessage": "",
  "infoMessage": "",
  "success": true,
  "type": "DeployApp",
  "vmDetailsData": {
    "appName": "",
    "errorMessage": "",
    "vmInstanceData": [
      {
        "hidden": false,
        "key": "Cloud Name",
        "value": "white"
      },
      {
        "hidden": false,
        "key": "Cloud Index",
        "value": "0"
      },
      {
        "hidden": false,
        "key": "Cloud Size",
        "value": "not so big"
      },
      {
        "hidden": false,
        "key": "Instance Name",
        "value": "angel vm__ca11f5"
      },
      {
        "hidden": true,
        "key": "Hidden stuff",
        "value": "something not for UI"
      }
    ],
    "vmNetworkData": [
      {
        "interfaceId": 0,
        "isPredefined": false,
        "isPrimary": true,
        "networkData": [
          {
            "hidden": false,
            "key": "MaxSpeed",
            "value": "1KB"
          },
          {
            "hidden": false,
            "key": "Network Type",
            "value": "Ethernet"
          }
        ],
        "networkId": 0,
        "privateIpAddress": "10.0.0.0",
        "publicIpAddress": "8.8.8.0"
      },
      {
        "interfaceId": 1,
        "isPredefined": false,
        "isPrimary": false,
        "networkData": [
          {
            "hidden": false,
            "key": "MaxSpeed",
            "value": "1KB"
          },
          {
            "hidden": false,
            "key": "Network Type",
            "value": "Ethernet"
          }
        ],
        "networkId": 1,
        "privateIpAddress": "10.0.0.1",
        "publicIpAddress": "8.8.8.1"
      }
    ]
  },
  "vmName": "angel vm__ca11f5",
  "vmUuid": "027ad770-9ecb-4936-a7df-aeaf526dfc34"
}
}

DeployAppResult properties

Name Type Description
actionId string (Mandatory) The action GUID as received (deploy_app_action.actionId) result must include the action id it results for, so server can match result to action.
deployedAppAddress string (Mandatory) The primary ip address of the VM instance. This value will be set as the deployed App’s resource address in CloudShell.
errorMessage string (Optional) Error message to be displayed to the sandbox end-user if VM deployment fails.
infoMessage string (Optional) Info message to be displayed to the sandbox end-user if VM deployment succeeds.
success bool (Mandatory)
type string (Read only) DeployApp object type. It is automatically set in DeployAppResult object type (in cloudshell-cp-core).
vmName string Unique name of the resource in CloudShell.
vmUuid string Unique resource id. Populate vmUuid with the unique id of the resource in your custom cloud provider. Cloudshell does not use this id, but will keep it for other method calls.
deployedAppAdditionalData dictionary Container used to persist custom data in resource, similar to AWS Tags. Included in all resource API query results. For example, reading the custom data and returning it in the VM Details.
deployedAppAttributes array Contains data describing the deployed app attributes, and are displayed in the App’s Attributes pane in the sandbox. It should be used to change default attribute values on the deployed App resource. For example User & Password attributes exist as part of the default deployed App model. If your custom cloud provider generates a password in runtime for the VM, you should update the deployedAppAttributes property accordingly.
vmDetailsData object Contains vmNetworkData and vmInstanceData. Displayed in the App’s VM Details pane. For details about the return data, see the GetVmDetails method’s Return value section below.

PowerOn method

The PowerOn method spins up the VM. It is run automatically when reserving the sandbox, as part of CloudShell’s default sandbox setup script, and can also be run manually by the sandbox end-user from the deployed App’s commands pane. During PowerOn, the VM’s IP address and a green live status icon are displayed on the App in sandbox.

You don’t have to implement this method if the deploy method has been configured to spin up the VM. If PowerOn does not fail, CloudShell will set resource state to “online” once the VM is up.

Signature

def PowerOn(self, context, ports)

Inputs

context: context is a ResourceRemoteCommandContext object that contains:

  1. connectivity - CloudShell server connectivity data for authentication with CloudShell Automation API
  2. resource - resource configuration settings entered by the user when creating the Cloud Provider resource in the Inventory dashboard
  3. remote_reservation – reservation details
  4. remote_endpoints- will contain a single ResourceContextDetails object which provides data for the operation.

Ports

Legacy argument. Obsolete for custom cloud providers.

PowerOn method implementation

The PowerOn method should perform the following steps:

1) Retrieve the cloud provider resource’s connection credentials.

2) Convert the deployed_app_json context from string to object.

     The json contains information about the CloudShell server, the deployed App and reservation.

     For details, copy the json contents into your preferred JSON editor. For example:

PowerOn JSON

3) Power on the deployed App resource.

PowerOn implementation example

src/driver.py view raw
def PowerOn(self, context, ports):
      """
      Will power on the compute resource
      :param ResourceRemoteCommandContext context:
      :param ports:
      """
      with LoggingSessionContext(context) as logger, ErrorHandlingContext(logger):
          self._log(logger, 'power_on_context', context)
          self._log(logger, 'power_on_ports', ports)
          cloud_provider_resource = L2HeavenlyCloudShell.create_from_context(context)
          resource_ep =  context.remote_endpoints[0]
          deployed_app_dict = json.loads(resource_ep.app_context.deployed_app_json)
          vm_uid = deployed_app_dict['vmdetails']['uid']
          HeavenlyCloudServiceWrapper.power_on(cloud_provider_resource,vm_uid)

Return value

None

Error handling

In case of an error, the command should raise an exception.

remote_refresh_ip

The remote_refresh_ip method retrieves the VM’s updated IP address from the cloud provider and sets it on the deployed App resource. The IP of the main network interface also needs to be retrieved from the cloud provider. Both private and public IPs are retrieved, as appropriate.

remote_refresh_ip is run automatically during the sandbox’s setup, after the VM is created and connected to networks, and can also be run manually by the sandbox end-user by running the Refresh IP command in the sandbox.

Note: This method is mandatory. However, you can choose to disable the call to this method during setup using the Wait for IP attribute. For details, see Controlling App Deployment Orchestration.

Signature

def remote_refresh_ip(self, context, ports, cancellation_context):

Inputs

context: context is a ResourceRemoteCommandContext object that contains:

  1. connectivity - CloudShell server connectivity data for authentication with CloudShell Automation API
  2. resource - resource configuration settings entered when creating the Cloud Provider resource in the Inventory dashboard
  3. remote_reservation – reservation details
  4. remote_endpoints - will contain a single ResourceContextDetails object which provides data for the operation.
cloudshell/shell/core/driver_context.py view raw
def __init__(self, connectivity, resource, remote_reservation, remote_endpoints):
    self.connectivity = connectivity  # Connectivity details that can help connect to the APIs
    """:type : ConnectivityContext"""
    self.resource = resource  # The details of the resource using the driver
    """:type : ResourceContextDetails"""
    self.remote_reservation = remote_reservation  # The details of the remote reservation
    """:type : ReservationContextDetails"""
    self.remote_endpoints = remote_endpoints
    """:type : list[ResourceContextDetails]"""

Ports

Legacy argument. Obsolete for custom cloud providers.

Cancellation context

cloudshell/shell/core/driver_context.py view raw
def __init__(self):
    self.is_cancelled = False
    """:type : bool"""

Return value

None.

Unlike other methods that update data using the result, remote_refresh_ip updates the deployed App resource with the IP by calling cloudshell-automation-api. However, if you implemented a return output, make sure to convert the remote_refresh_ip object to a string and pass the value to the “IP” attribute on the deployed App.

Error handling

If the operation fails, the command should raise an exception.

remote_refresh_ip method implementation

This method should perform the following steps:

  1. Retrieve the Cloud Provider resource’s connection credentials.
  2. Convert the deployed_app_json context from string to object.
  3. Retrieve previously known private/public IPs (if there are any), VM instance id.
  4. Verify that the deployed App’s private IP is the same as the ip in the cloud provider. If it’s different, update the deployed App ip with the IP on the cloud provider.
  5. If needed, verify that the deployed App’s public IP is the same as the ip in the cloud provider.

GetVmDetails method

The GetVmDetails method gets information about the App’s VM, operating system, specifications and networking information. It is called by the default setup script when reserving the sandbox, after the RefreshIp method is called, and can also be run manually by the sandbox end-user on deployed Apps from the App’s VM Details pane.

Note: The implementation is expected to query the cloud provider for the details, but not return any cached or stored data.

Signature

def GetVmDetails(self, context, requests, cancellation_context):

Inputs

context: context is a ResourceCommandContext object that contains:

  1. connectivity - CloudShell server connectivity data for authentication with CloudShell Automation API
  2. resource - resource configuration settings entered when creating the Cloud Provider resource in the Inventory dashboard
  3. reservation – reservation details
  4. connectors – details of any visual connectors between the Cloud Provider App and other endppoints in the sandbox
cloudshell/shell/core/driver_context.py view raw
class ResourceCommandContext:
    def __init__(self, connectivity, resource, reservation, connectors):
        self.connectivity = connectivity  # Connectivity details that can help connect to the APIs
        """:type : ConnectivityContext"""
        self.resource = resource  # The details of the resource using the driver
        """:type : ResourceContextDetails"""
        self.reservation = reservation  # The details of the reservation
        """:type : ReservationContextDetails"""
        self.connectors = connectors  # The list of visual connectors and routes that are connected to the resource (the resource will be considered as the source end point)
        """:type : list[Connector]"""

Requests

JSON string that contains a list of items containing App requests and deployed App data. This method can be called for a set of VMs.

Cancellation request

cloudshell/shell/core/driver_context.py view raw
def __init__(self):
    self.is_cancelled = False
    """:type : bool"""

Return value

VmDetailsData object in a serialized JSON.

package/cloudshell/cp/core/models.py view raw
def __init__(self, vmInstanceData=None, vmNetworkData=None,appName = '',errorMessage = ''):
    """
    :param vmInstanceData: [VmDetailsProperty]
    :param vmNetworkData:  [VmDetailsNetworkInterface]
    :param appName:        str
    :param errorMessage:   str
    """

    self.vmInstanceData = vmInstanceData if vmInstanceData else []  # type: [VmDetailsProperty]
    self.vmNetworkData = vmNetworkData if vmNetworkData else []  # type: [VmDetailsNetworkInterface]
    self.appName = appName
    self.errorMessage = errorMessage

vmDetailsData properties

vmDetailsData is used to describe the App’s VM. All properties are optional.

Name Type Description
appName String The App’s name. No need to assign it in the deploy operation. Must be assigned in getVmDetails method.
errorMessage string Indication message to be displayed to the sandbox end-user when getting the vmDetails.
vmNetworkData array Array of cloudshell-cp-core VmDetailsNetworkInterface object. Create a vmNetworkData object for each VM NIC you wish to associate with resource. See the VmDetailsNetworkInterface table below.
vmInstanceData array Array of cloudshell-cp-core’s VmDetailsProperty. Contains data about the VM instance attributes. It should be used to change persist values of the VM resource. For example to persist Storage and operating system data. See the VmDetailsProperty table below.

VmDetailsNetworkInterface

Name Type Description
interfaceId String The network interface id with which the address is associated.
networkId string The unique id of the network associated with the network interface.
isPrimary bool Determines if NIC is primary. Primary affects the default selected network in VmDetailsTab in cloudshell
isPredefined bool Determines if NIC is predefined. Predefined means that the network existed before the sandbox reservation. for example, a Static Management network that is not modeled in the blueprint.
networkData array Array of cloudshell-cp-core VmDetailsProperty. Contains data describing the NIC. Examples of network properties include Device Index and MAC Address.
privateIpAddress string NIC address.
publicIpAddress string The public ip associated with the NIC’s private ip.

VmDetailsProperty

Name Type Description
key string  
value string  
hidden bool Determines if the property is displayed to the sandbox end-user.

GetVmDetails method implementation

This method should perform the following steps:

  1. Retrieve cloud provider resource connection credentials.
  2. Convert the JSON string to object
  3. For each request, do the following:
  4. Convert to JSON and return the result.