Pattern-type (Part 12): Call a service to insert parameters in the vm topology.

The provided Java API has a number of interfaces, one of them is the PostProvisioner on which I already wrote a blog (Pattern-type (Part 11): Add a post processor to a deployment) another one is the ServiceProvisioner. With this interface you can insert parameter value in the vm topology.

For example, you have a service which retreives some information. This service can be launched when the topology is created and add new parameters in the topology. These parameter can be used afterward in the role scripts.

The service contains 2 main methods, createService and deleteService. One of the parameter is the JSONObject serviceDescription. The createService can add JSONObject in the serviceDescription. The added object will be added in the topology role as parameters where the service has been referenced.

Let’s see how to implement the ServiceProvisioner and the different steps to do are similar than the one for the PostProvisioner.

1) Create a java class which implements the ServiceProvisioner interface.

2) Create an OSGI service component for this class.

3) Add this OSGI file to the manifest along the package needed to run this class.

4) Add the “service-templates” array element to list all services provisioning you would like to run at the end of the deployment.

5) Add a reference to the service in a role.

6) Update the role install.py script to retrieve the inserted parameter.

Create the Java Class:

We have to create a java class that implement the ServiceProvisioner interface; 3 methods have to be implemented, the createService, the deleteService and the getServiceStateAndDescription. For the last one, please refer to the PDK javadoc embedded in the PDK package.

public StateAndDescription createService(String serviceReferenceName, JSONObject serviceDescription,RestClient restClient) throws Exception {
     logger.info(“Create Service”);
    serviceDescription.put(“param1”, “ServiceCreationDate:”+new Date());
    logger.info(serviceDescription.serialize());
    return new StateAndDescription(State.AVAILABLE, serviceDescription);
}

This method will add a parameter “param1” with the value “ServiceCreationDate”+new Date() in the parms section of the role.

parms”: {
“servicename”: null,
    “param1”: “ServiceCreationDate:Sat Nov 10 02:47:58 EST 2012”,
“deployment_id”: “d-4d9178ae-f820-46cd-aadc-943b244cdb1d”,
“cloud_group”: “1”,
“service-ref”: “master-service-provisioner”
},

N.B.: the servicename is null because we didn’t create a sharedservice.

The deleteService is like:

public StateAndDescription deleteService(String serviceReferenceName, JSONObject serviceDescription,RestClient restClient) throws Exception {
   logger.info(“Delete Service”);
   logger.info(serviceDescription.serialize());
   logger.info((String)serviceDescription.get(“param1”));
   return new StateAndDescription(State.DELETED, serviceDescription);
}

You can see the deleteService can reuse the parameter inserted by the “createSerivce” method.

Create the OSGi component

This is very simple, we have just to reference the class which implements the ServiceProvisioner interface. The name will be use to reference this service in the “service-templates” section of the vm topology.

<?xml version=”1.0″ encoding=”UTF-8″?>
<scr:component xmlns:scr=“http://www.osgi.org/xmlns/scr/v1.1.0”name=“masterServiceProvisioner”>
<implementationclass=“com.itdove.iwd.lab.MasterServiceProvisioner”/>
<service>
<provideinterface=“com.ibm.maestro.iaas.ServiceProvisioner”/>
</service>
</scr:component>

Add the OSGi component in the MANIFEST

Open the MANIFEST.MF and add the OSGi file:

Service-Component:OSGI-INF/slave.xml, OSGI-INF/master.xml, OSGI-INF/masterslave.xml, OSGI-INF/masterPostDeployment.xml, OSGI-INF/masterServiceProvisioner.xml

Add the service-templates array in the topology

Open the topology from where you would like to call your newly created service and add these lines at the same level as the “vm-templates”:

    “service-templates”: [{
“type”: “masterServiceProvisioner”,
“name”: “master-service-provisioner”
}],

The type value is the name you give in the OSGi component.
The name will be use to reference the service inside the vm-template.

Add a service reference to a role

In the role section where you would like to call the service and insert the parameters add a reference to the service as follow:

“roles”: [
{
“type”: “master”,
“name”: “master”,
parms“:{
       “service-ref“: “master-service-provisioner”,
}
}

Once the topology will be generated this section will be transformed as:

{
“parms”: {
“servicename”: null,
“param1”: “ServiceCreationDate:Sat Nov 10 02:47:58 EST 2012”,
“deployment_id”: “d-4d9178ae-f820-46cd-aadc-943b244cdb1d”,
“cloud_group”: “1”,
“service-ref”: “master-service-provisioner”
},
“type”: “master”,
“name”: “master”

You can see the “param1” has been inserted where we add the service reference.

Update role install.py script to retrieve the parameter

In the same role, we will update the install.py script to retrieve the parameter.

import logging
import maestro
logger = logging.getLogger(“master/install.py”)
par1 = maestro.parms[‘param1’];
logger.debug(‘Install ServiceReturnParameterValue %s’ % par1);

Test

I launched now a pattern with my “master” component, we check the topology to see the modification and then look at the log file and we will find:

10270 DEBUG Install ServiceReturnParameterValue ServiceCreationDate:Sat Nov 10 02:47:58 EST 2012

Which is the log I added in the install.py.