Write Jython Scripts

The mapping script is a regular Jython script, and should follow the rules for Jython scripts. For details, see Developing Jython Adapters.

The script should contain the DiscoveryMain function, which may return either an empty OSHVResult or a DataPushResults instance upon success.

To report any failure, the script should raise an exception, for example:

raise Exception('Failed to insert to remote UCMDB using TopologyUpdateService. See log of the remote UCMDB')

In the DiscoveryMain function, the data items to be pushed to or deleted from the external application can be obtained as follows:

# get add/update/delete result objects (in XML format) from the Framework
addResult = Framework.getTriggerCIData('addResult')
updateResult = Framework.getTriggerCIData('updateResult')
deleteResult = Framework.getTriggerCIData('deleteResult')

The client object to the external application can be obtained as follows:

oracleClient = Framework.createClient()

This client object automatically uses the credentials ID, host name and port number passed by the adapter through the Framework.

If you need to use the connection parameters that you defined for the adapter (for details, see the step on editing the discoveryPatterns\push_adapter.xml file in Build an Adapter Package), use the following code:

propValue = str(Framework.getDestinationAttribute('<Connection Property Name'))

For example:

serverName = Framework.getDestinationAttribute('ip_address')

This section also includes:

Working with the Mapping's Results

Generic push adapters create XML strings that describe the data to be added, updated, or deleted from the target system. The Jython script needs to analyze this XML, and then performs the add, update, or delete operation on the target.

In the XML of the add operation that the Jython script receives, the mamId attribute for the objects and links is always the UCMDB identifier of the original object or link before its type, attribute, or other information was changed to the schema of the remote system.

In the XML of the update or remove operations, the mamId attribute of each object or link contains the string representation of the same ExternalId that was returned from the Jython script from the previous synchronization.

In the XML, the id attribute of a CI holds the cmdbId as an external id or the ExternalId of that CI if the CI got an ExternalId one when the CI was sent to the script. The end1Id and end2Id fields of the link hold for each of the link's ends the cmdbId as an external id or the ExternalId of that link’s end if the CI at the link’s end got an ExternalId when it was sent to the script.

When processing the CIs in the Jython script, the return value of the script is a mapping between the CI's CMDB id and the given id (the id given to each CI in the script). If a CI is pushed for the first time, the id that is in the XML of that CI is the CMDB id. If a CI is not pushed for the first time, the CI’s id is the same id that was given to that CI in the script when it was first pushed.

The id is retrieved from the CI XML script as follows:

  1. From the CI Element in the XML, retrieve the id from the id attribute. For example: id = objectElement.getAttributeValue('id').

  2. After retrieving the id from the XML, restore the id from the attribute (string). For example: objectId = CmdbObjectID.Factory.restoreObjectID(id).

  3. Check if the objectId received in the previous step is the CMDB id. You can do this by checking if the objectId has the new id that is given to it by the script. If it does, the returned id is not the CMDB id. For example: newId = objectId.getPropertyValue(<the name of the id attribute which is given by the script>).

    If newId is null, then the id that was returned in the XML is a CMDB id.

  4. If the id is a CMDB id (that is, newId is null), perform the following (if the id is not a CMDB id, go to step 5):

    1. Create a property for that CI that holds the new id. For example: propArray =[TypesFactory.createProperty('<the name of the id attribute which is given by the script>', '<new id>')].

    2. Create an externalId to that CI. For example: cmdbId = extI.getPropertyValue('internal_id')
      className = extI.getType()
      externalId = ExternalIdFactory.createExternalCiId(className, propArray)

    3. Map the CMDB id to the newly created externalId (and in the next step return that mapping to the adapter). For example: objectMappings.put(cmdbId, externalId)

    4. When all of the CIs and links are mapped: updateResult = DataPushResultsFactory.createDataPushResults(objectMappings, linkMappings);
      return updateResult

  5. If the id is the new id (that is, newId is not null), then the externalId is the newId.

It is also possible to report on the push status for each CI and link as follows:

  1. updateStatus = ReplicationActionDataFactory.createUpdateStatus();

    where updateStatus is an instance of the UpdateStatus class that contains statuses of the CIs and links.

  2. Add a status to updateStatus by calling the reportCIStatus or reportRelationStatus method.

    For example:

    status = ReplicationActionDataFactory.createStatus(Severity.FAILURE, 'Failed', ERROR_CODE_CI, errorParams,Action.ADD);
    updateStatus.reportCIStatus(externalId, status);

    Where ERROR_CODE_CI is the number of the error messages as they appear in adapter properties.errors file (for details on the properties.errors file, see Error-Writing Conventions), and errorParams contains the parameters to pass to the message. See ReplicationActionDataFactory javadoc for more details.

  3. Create a push result with the statuses as follows:

    updateResult = DataPushResultsFactory.createDataPushResults(objectMappings, linkMappings, updateStatus);
    return updateResult

Example of the XML result

<root>
  <data>
    <objects>
      <Object mode="update_else_insert" name="UCMDB_UNIX" operation="add" mamId="0c82f591bc3a584121b0b85efd90b174" id="HiddenRmiDataSource%0Aunix%0A1%0Ainternal_id%3DSTRING%3D0c82f591bc3a584121b0b85efd90b174%0A">
	<field name="NAME" key="false" datatype="char" length="255">UNIX5</field>
	<field name="DATA_NOTE" key="false" datatype="char" length="255"></field>
      </Object>
    </objects>
    <links>
	<link targetRelationshipClass="TALK" targetParent="unix" targetChild="unix" operation="add" mode="update_else_insert" 
mamId="265e985c6ec51a8543f461b30fa58f81" 
id="end1id%5BHiddenRmiDataSource%0Aunix%0A1%0Ainternal_id%3DSTRING%3D41372a1cbcaba27b214b84a2ec9eb535%0A%5D%0Aend2id%
5BHiddenRmiDataSource%0Aunix%0A1%0Ainternal_id%3DSTRING%3D0c82f591bc3a584121b0b85efd90b174%0A%5D%0AHiddenRmi
DataSource%0Atalk%0A1%0Ainternal_id%3DSTRING%3D265e985c6ec51a8543f461b30fa58f81%0A">
	<field name="DiscoveryID1">41372a1cbcaba27b214b84a2ec9eb535</field>
	<field name="DiscoveryID2">0c82f591bc3a584121b0b85efd90b174</field>
	<field name="end1Id">HiddenRmiDataSource%0Aunix%0A1%0Ainternal_id%3DSTRING%3D41372a1cbcaba27b214b84a2ec9eb535%0A</field>
	<field name="end2Id">HiddenRmiDataSource%0Aunix%0A1%0Ainternal_id%3DSTRING%3D0c82f591bc3a584121b0b85efd90b174%0A</field>
	<field name="NAME" key="false" datatype="char" length="255">TALK4</field>
	<field name="DATA_NOTE" key="false" datatype="char" length="255"></field>
	</link>
    </links>
  </data>
</root>

Note If datatype="BYTE", the returned result's value is a String that is generated as: new String([the byte array attribute]). The byte[] object can be reconstructed by: <the received String>.getBytes(). If there are differences in the default locale between the server and the probe, the reconstruction is performed according to the server's default locale.

Handling Test Connection in the Script

A Jython script can be invoked to test the connection with an external application. In this case, the testConnection destination attribute will be true. This attribute can be obtained from the Framework as follows:

testConnection = Framework.getTriggerCIData('testConnection')

When run in test connection mode, a script should raise an exception if a connection to the external application cannot be established. Otherwise, if the connection is successful, the DiscoveryMain function should return an empty OSHVResult.