IBM Support

Explicit Relationships: How to create NCIM relationships via Collectors (4.1+)

Technical Blog Post


Explicit Relationships: How to create NCIM relationships via Collectors (4.1+)


This blog entry provides a reminder/introduction to some useful Collector functionality that was introduced in ITNM 4.1 to support the RAN work but which is generally useful beyond RAN integrations.


In ITNM 4.1 a set of relationship methods were added to the Collector framework that allow NCIM relationships (collects, contains, hostedService, depends) to be specified in Collector data.

The additional methods that provide these facilities are documented in the language specific archives that accompany the Collector Developer Guide on SMC: 

The methods and associated NCIM relationship are listed below;
Store MethodNCIM Relationship
DeviceCollects() / InterfaceCollects() / AddGenericRelationship()collects
DeviceHosts() / InterfaceHosts() / AddGenericRelationship()hostedService
DeviceDependency() / InterfaceDependency() / AddGenericRelationship()dependency

If you add such relationships in your Collector then they will flow to DNCIM/NCIM as follows;

  1. The CollectorDetails or CollectorInventory Agent receives the relationship data via <extrainfo> and places it into m_ExtraInfo for the interface or device
  2. The data flows to workingEntities.finalEntity as is
  3. The discovery processes take the relationship data from the workingEntities fields (as specified in ModelNcimDb.cfg) and will automatically do any entity resolution (e.g. resolving m_DeviceId data to associated discovered entity)
  4. The relationship will be stored in DNCIM/NCIM using the resolved entities 



Example: Hosting a virtual device as a service on the physical host

The user has a situation where device A is physical and hosts virtual devices B, C and D. 
They want to show this relationship in NCIM and the GUI's Structure Browser by making use of NCIM's hostedService relationship such that A hosts B, C and D.
For this example we will use the example data (exampleCsv.cfg) shipped with the GenericCSV Collector.
We'll assume that devices A, B, C and D map to the example devices as follows;

    A =    B =    C =    D =

To hold our relationships we will create a new CSV file, hostedServices.csv, in GenericCsv/exampleCsvData/ as follows;
-- hostedServices.csv
-- hostDeviceId,serviceDeviceId,,,
We now have our relationship file but need to modify the existing example .cfg & .drv config files to support it;


        - add this line to the end of the 'file=>' config;
HostedServiceData  => './exampleCsvData/hostedServices.csv'
        - add this line to the end of the 'delimiter=>' config;
HostedServiceData   => ','
        - add this to the end of the 'mappingGroupDescriptions=>' config;
'HostedServiceData' =>
    Description => 'One row per entity per hosted service',
    DelimetedBy => ',',
    UseColumns => '*',
        - add this to the end of the 'mappingGroupDefinitions=>' config;
'HostedServiceData' =>
    1 =>
        Name => 'hostDeviceId',
        Description => 'the device hosting the service. BaseName.',
        MapsTo => 'hostDeviceId'
    2 =>
        Name => 'serviceDeviceId',
        Description => 'the service hosted. BaseName',
        MapsTo => 'serviceDeviceId'

Next we need to modify the GenericCSV Collector to load our relationship data and add it to the Store. So make the following alterations;;

    - modify LoadData() to call our new relationship loader by putting this at the end:
$self->LoadHostedServices( $store, $source );
    - Add our LoadHostedServices() method:
sub LoadHostedServices()
    my $self = $_[0];
    my $store = $_[1];
    my $sourceId = $_[2];
    my $services = $self->LoadCsvFile( 'HostedServiceData' );
    if( $services )
        foreach my $serviceRelation (@$services)
            my $hostingDeviceId = $serviceRelation->{hostDeviceId} 
                                    if exists $serviceRelation->{hostDeviceId} ;
            my %hostedData;
            $hostedData{m_DeviceId} =  $serviceRelation->{serviceDeviceId}
                                    if exists $serviceRelation->{serviceDeviceId};
            $store->DeviceHosts( $sourceId, $hostingDeviceId, \%hostedData );
And that would be it were not for an issue currently in ModelNcimDb.cfg for hostedServices support (fixed in 4.1.1 FP1), so lets fix that while we're here;
    Modify $NCHOME/etc/precision/ModelNcimDb.cfg and change "hostedServices" to "hostedService", i.e. it should read;

     hostedService = "eval(list type atom, '&m_ExtraInfo->hostedService')",



You can confirm your change using, e.g.
ncp_perl /opt/IBM/tivoli/netcool/precision/scripts/perl/scripts/ -port 8081
      <descr>Cisco Internetwork Operating System Software IOS (tm) c6sup2_rp Software (c6sup2_rp-PK9SV-M), Version 12.2(18)SXD6, RELEASE SOFTWARE (fc1) Technical Support: Copyright (c) 1986-2005 by cisco Systems, Inc.  Compiled Wed</descr>
        <hostedService type="list">

Or run a discovery and see your relationship in NCIM..

ncp_oql -domain NCOMS -service NCIM -username ncim -tabular -query "select e1.entityName as Service, e2.entityName as Host from hostedService s inner join entityData e1 on e1.entityId=s.hostedEntityId inner join entityData e2 on e2.entityId=s.hostingEntityId;"
| SERVICE    | HOST     |
| | |
| | |
| | |
 3 rows(s)

Or, as our user ultimately wanted in this example, the GUI;


[{"Business Unit":{"code":"BU004","label":"Hybrid Cloud"},"Product":{"code":"","label":""},"Component":"","Platform":[{"code":"","label":""}],"Version":"","Edition":""}]