Traversals

A SEARCH expression creates a set of nodes, and a LOOKUP makes a set with just one node in it. With that set, a query can TRAVERSE from each of the nodes to a new set of related nodes. The format of a TRAVERSE expression is

TRAVERSE role:rel:role:kind [WHERE clause]

The WHERE clause allows the new set to be further filtered.
For example, to find all software instances that are running on Linux hosts:

SEARCH Host WHERE os_type HAS SUBWORD "Linux" 
TRAVERSE Host:HostedSoftware:RunningSoftware:SoftwareInstance

As with key expressions, elements of the traversal can be omitted as a wildcard mechanism. All matching relationships are followed, so this example finds software running on Linux hosts, and virtual machine software containing the hosts:

SEARCH Host WHERE os_type HAS SUBWORD "Linux" 
TRAVERSE :::SoftwareInstance

Adding some filtering:

SEARCH Host WHERE os_type HAS SUBWORD "Linux" 
TRAVERSE :HostedSoftware::SoftwareInstance
WHERE type HAS SUBSTRING "oracle"

The attributes that are accessed in the TRAVERSE WHERE clause are attributes of the nodes that have been traversed to, not attributes of the original nodes. The original nodes have been discarded from the set.

Traversals can be chained, so we can now find any business application instances related to the software instances:

SEARCH Host WHERE os_type HAS SUBWORD "Linux" 
TRAVERSE :HostedSoftware::SoftwareInstance
WHERE name HAS SUBSTRING "oracle"
TRAVERSE ContainedSoftware:SoftwareContainment:
         SoftwareContainer:BusinessApplicationInstance

At each stage, the result of a traversal is a set, so each node appears only once in the set, even if it is reached via relationships from more than one node.

A TRAVERSE clause performs one single traverse from each node in the current set. Sometimes it is useful to repeatedly traverse to find all the nodes that can be reached via particular relationships, using an EXPAND clause. This is useful for finding all applications that depend on a particular other application, for example:

SEARCH BusinessApplicationInstance WHERE <some condition>
  EXPAND DependedUpon:Dependency:Dependant:BusinessApplicationInstance

The set now contains the original nodes, plus all the nodes that depend upon them, via any number of intermediate dependencies. The EXPAND keeps performing traversals until no more nodes are found. The EXPAND always keeps the original set. If you want to EXPAND but not keep the original set, use a TRAVERSE followed by an EXPAND:

SEARCH BusinessApplicationInstance WHERE <some condition>
  TRAVERSE DependedUpon:Dependency:Dependant:BusinessApplicationInstance
  EXPAND DependedUpon:Dependency:Dependant:BusinessApplicationInstance

Just like a TRAVERSE clause, an EXPAND can have a WHERE clause. The filtering of the WHERE clause happens once the EXPAND has completed, not on every traversal iteration (since if it did it every iteration, it might never complete).

TRAVERSE and EXPAND move from one set of nodes to another set of nodes. Sometimes, you want to stop off at a relationship along the way. This is achieved with STEP IN, which replaces the set of nodes with a set of relationships. Given a set of relationships, you can STEP OUT to another set of nodes. To find critical Dependency relationships:

SEARCH BusinessApplicationInstance WHERE <some condition> 
STEP IN DependedUpon:Dependency WHERE critical

To find the BusinessApplicationInstances that have a critical dependency to the ones matched in the WHERE clause:

SEARCH BusinessApplicationInstance WHERE <some condition>
STEP IN DependedUpon:Dependency WHERE critical
STEP OUT Dependant:BusinessApplicationInstance

To find a relationship between 2 named nodes:

SEARCH Host where name="My_host" step in Host:HostedSoftware where #:RunningSoftware:SoftwareInstance.name="My SI"

To find all the relationships between 2 named nodes:

SEARCH Host where name="My_host" step in : where #::SoftwareInstance.name="My SI"

Named and filtered sub-traversals

To see the types of all the SoftwareInstances running on each Host, you can use the following traversal:

search Host show name, #Host:HostedSoftware:RunningSoftware:SoftwareInstance.type

You can also use a named traversal to do the same thing:

search Host 
  with (traverse Host:HostedSoftware:RunningSoftware:SoftwareInstance as si) 
  show name, #si.type

You can filter the results using a WHERE clause:

search Host  
  with (traverse Host:HostedSoftware:RunningSoftware:SoftwareInstance as si where type has subword "server") 
  show name, #si.type

An example of how these can be used is to find named attributes on Detail nodes. For example, a standard TKU pattern creates "LPAR Resource" Detail nodes with additional details about LPAR allocations for AIX machines. One of the attributes on those Details is entitled_capacity. Using a key expression to find it:

search Host 
  where os_type = "AIX" 
  show name, os, #ElementWithDetail:Detail:Detail:Detail.entitled_capacity as "Entitled Capacity"

As there are other, completely different Detail nodes related to those Hosts which do not have an entitled_capacity attribute, so they show as "None". For example:

Using a named traversal, we can filter out the non-matching nodes.

search Host
  with (traverse ElementWithDetail:Detail:Detail:Detail as detail where type = "LPAR Resource")
  where os_type = "AIX" show name, os, #detail.entitled_capacity as "Entitled Capacity"

For example:

The last host in the list had five Nones before, meaning it had five non-matching Detail nodes, and no LPAR Resource Detail. Now it reports "Not set", because there was nothing matching.

Similarly, when Software Instances are modeled running on a Cluster, they are given "ClusteredSoftware" relationships to each of the Host nodes that are in the cluster, to efficiently answer the common question of which software is on which hosts. When the Cluster node represents a fail-over cluster, one Host is "active" and the others are not. BMC Discovery sets an "active" attribute on the relationship leading to the Host that was most recently seen to be the active one. Because the data is on the relationship, it can be tricky to access. Using a simple key expression to access the Host for SoftwareInstances in fail-over clusters:

search Cluster where failover
  traverse Host:HostedSoftware:RunningSoftware:SoftwareInstance
  show name, #ClusteredSoftware:HostedSoftware:Host:Host.name as "Host name"

Each SI reports two hosts, because these are fail-over clusters of two hosts. We cannot see which one is active.

Using a traversal expression to access the relationship and the target node:

search Cluster where failover
  traverse Host:HostedSoftware:RunningSoftware:SoftwareInstance
  with (traverse ClusteredSoftware:HostedSoftware:Host:Host as rel, host where #rel.active)
  show name, #host.name as "Host name"

We see just the active Host for each SI.



Was this page helpful? Yes No Submitting... Thank you

Comments