Example Discovery pattern

This example describes the steps in a discovery pattern that discovers F5 load balancers and adds them to the CMDB.

Discovery pattern form configuration

In this example, the discovery pattern is configured as follows:

F5 discovery pattern form fields
Field Value Description
Name F5 example pattern A descriptive name for the pattern.
Pattern type 3 - Discovery Host The type of pattern. The Discovery Host selection specifies that Discovery uses this pattern to discover a device, rather than an application.
CI type F5 BIG-IP [cmdb_ci_lb_bigip] The table in the CMDB that stores F5 load balancers.
Active selected The pattern is active and ready for Discovery to use.
The pattern looks like this in the pattern designer:
Figure 1. F5 load balancer discovery pattern in the pattern designer
F5 load balancer discovery pattern in the pattern designer

The CI classification

A CI classification is required for all discovery patterns. In this example, an SNMP CI classification runs on the F5 BIG-IP table, and specifies both a DNS and horizontal discovery probe for exploration and identification.
Figure 2. CI classification for F5 discovery pattern
CI classification for F5 discovery pattern

Step 1: get_device_data

Operation: SNMP query

This step specifies the tabular type of MIB. It also specifies:
  • The variables table name and SNMP object identifiers (OIDs) for the table.
  • Two additional columns and an OID for each column.
Settings Neebula Discovery Language (NDL) script equivalent
SNMP variables and OIDs
step { 
  name = "get_device_data"
  run_snmp_to_var { 
    snmp_object_ids = table { 
      name = "1.3.6.1.2.1.1" 
      col_names = "5","2" 
    } 
    var_names = table { 
      name = "device_main_data" 
      col_names = "name","model_number" 
    } 
    if_not_found_do = nop {} 
  } 
}

Step 2: get_serial_number

Operation: SNMP query

This step is similar to other SNMP query steps, but specifies a different variable table, columns, and OIDs.

Settings NDL script equivalent
SNMP variables and OIDs
step { 
  name = "get_serial_number" 
  run_snmp_to_var { 
    snmp_object_ids = table { 
      name = "1.3.6.1.4.1.3375.2.1.3.3" 
      col_names = "3" 
    } 
    var_names = table { 
      name = "device_serial_number" 
      col_names = "serial_number" 
    } 
    if_not_found_do = nop {} 
  } 
}

Step 3: create_device_ci

Operation: Merge table

This step merges records from two source tables, the first of which is the variable table used in a previous SNMP query step (device_serial_number), with the records from the F5 BIG-IP [cmdb_ci_lb_bigip] table. This table is the same as the table specified in the CI type field on the pattern form.

The pattern also specifies that non-matching rows are removed. The "true" Equals "true" condition species that all records should be joined in the table merge.

Settings NDL script equivalent
Merge table settings
step { 
  name = "create_device_ci" 
  merge { 
    table1_name = "device_serial_number"
    table2_name = "cmdb_ci_lb_bigip"
    result_table_name = "cmdb_ci_lb_bigip"
    unmatched_lines = remove
    condition = eq {
      "true"
      "true"
     }
    }
}

Step 4: add_device_name

Operation: Merge table

This step merges records from the device_main_data table that was populated in step 1 with the records in the F5 BIG-IP [cmdb_ci_lb_biggie] table.

The pattern also specifies that non-matching rows are removed. The "1" Contains "1" condition species that all records should be joined in the table merge.

Settings NDL script equivalent
Merge table settings
step { 
  name = "add_device_name" 
  merge { 
    table1_name = "device_main_data"
    table2_name = "cmdb_ci_lb_bigip"
    result_table_name = "cmdb_ci_lb_bigip"
    unmatched_lines = remove
    condition = contains {
      "1"
      "1"
     }
    }
}

Step 5: get_interfaces

Operation: SNMP query

This step discovers interfaces on load balancers.

Settings NDL script equivalent
SNMP variables and OIDs
step { 
  name = "get_interfaces" 
  run_snmp_to_var { 
    snmp_object_ids = table { 
      name = "1.3.6.1.4.1.3375.2.1.2.4.1.2.1" 
      col_names = "1","6" 
    } 
    var_names = table { 
      name = "device_serial_number" 
      col_names = "name","mac_address" 
    } 
    if_not_found_do = nop {} 
  } 
}

Step 6: interfaces_ref_device

Operation: Relation and/or Reference

This step creates relationships and references between CIs in a source table and a target table. In this case, the source table is the Load Balancer Interface [cmdb_ci_lb_interface] table that was used in a previous step for an SNMP query, and the target table is the F5 BIG-IPs [cmdb_ci_lb_bigip] table. The results are put into the interface_device table.

The Relationship type specifies that the interface runs on the load balancer device, while the Direction specifies that the interface is the parent in the relationship.

The load_balancer column is the reference field that is used between the source and target table.

The pattern also specifies that non-matching rows are removed. The "true" Equals "true" condition species that all records should be joined in the table merge.

Settings NDL script equivalent
Relation and reference to the CMDB
step {
  name = "interfaces_ref_device"
  relation_reference {
    table1_name = "cmdb_ci_lb_interface"
    table2_name = "cmdb_ci_lb_bigip"
    result_table_name = "interface_device"
    unmatched_lines = remove
    condition = eq {
      "true"
      "true"
     }
     relation_type = "Runs on::Runs"
     ref_direction = parentToChild
     ref_field_name = "load_balancer"
   }
}

Step 7: get_vlans

Operation: SNMP query

This step discovers load balancer VLANs

Settings NDL script equivalent
SNMP variables and OIDs
step {
  name = "get_vlans"
  run_snmp_to_var {
    snmp_object_ids = table {
      name = "1.3.6.1.4.1.3375.2.1.2.13.1.2.1"
      col_names = "1"
    }
    var_names = table {
      name = "cmdb_ci_lb_vlan"
      col_names = "name"
    }
    if_not_found_do = nop {}
  }
}

Step 8: vlans_ref_device

Operation: Relation and/or Reference

This step creates a relationship and reference between the VLANs discovered in the previous step, and the load balancers in the F5 BIG-IPs [cmdb_ci_lb_bigip] table. The results are put into the vlans_to_device table.

The Relationship type specifies that the VLAN runs on the load balancer device, while the Direction specifies that the VLAN is the parent in the relationship.

The load_balancer column is the reference field that is used between the source and target table.

The pattern also specifies that non-matching rows are removed. The "true" Equals "true" condition species that all records should be joined in the table merge.

Settings NDL script equivalent
Relation and reference to the CMDB
step {
  name = "vlans_ref_device"
  relation_reference {
    table1_name = "cmdb_ci_lb_vlan"
    table2_name = "cmdb_ci_lb_bigip"
    result_table_name = "vlans_to_device"
    unmatched_lines = remove
    condition = eq {
      "true"
      "true"
    }
    relation_type = "Runs on::Runs"
    ref_direction = parentToChild
    ref_field_name = "load_balancer"
  }
}

Step 9: get_vips_snmp

Operation: SNMP query

This step discovers virtual IPs on load balancers

Settings NDL script equivalent
Discovering Virtual IPs on load balancers
step {
  name = "get_vips_snmp"
  run_snmp_to_var {
    snmp_object_ids = table {
      name = "1.3.6.1.4.1.3375.2.2.10.1.2.1"
      col_names = "3","1","6"
     }
   var_names = table {
     name = "cmdb_ci_lb_service"
     col_names = "ip_address","name","port"
   }
   if_not_found_do = nop {}
  }
}

Step 10: get_vip_status_snmp

Operation: SNMP query

This step discovers the status of virtual IPs

Settings NDL script equivalent
Discovering virtual IP status
step {
  name = "get_vip_status_snmp"
  run_snmp_to_var {
    snmp_object_ids = table {
      name = "1.3.6.1.4.1.3375.2.2.10.13.2.1"
      col_names = "1","2"
    }
    var_names = table {
      name = "vip_status"
      col_names = "name","operational_status"
    }
    if_not_found_do = nop {}
  }
}

Step 11: merge_VIP_status_to_vip

Operation: Merge table

This step merges the status of virtual IPs to the Load Balancer Service [cmdb_ci_lb_service] table. The merge criteria specifies that the name field on the two tables must have the same value.

Settings NDL script equivalent
step {
  name = "merge_vip_status_to_vip"
  merge {
    table1_name = "vip_status"
    key1_name = "name"
    table2_name = "cmdb_ci_lb_service"
    key2_name = "name"
    result_table_name = "cmdb_ci_lb_service"
    unmatched_lines = remove
  }
}

Step 12: fix service IP

Operation: Transform table

This step adds the ip_address column to the Load Balancer Service [cmdb_ci_lb_service] table.

Settings NDL script equivalent
Transform table
step {
  name = "fix service IP"
  transform {
    src_table_name = "cmdb_ci_lb_service"
    target_table_name = "cmdb_ci_lb_service"
    operation {
      set_field {
        field_name = "ip_address"
        value = concat {
          eval {
            "javascript:var rtrn = '';
            String.prototype.getBytes = function() {
              var bytes = [];
              for (var i = 0; i < this.length; ++i) {
                bytes.push(this.charCodeAt(i));
              }
              return bytes;
            };
            var ip_col = $ {
              cmdb_ci_lb_service[].ip_address
            };
            var ip = Packages.com.snc.sw.context.support.net.IPUtils.hex2String(ip_col);
            if (Packages.com.snc.sw.context.support.net.IPUtils.isIPAddress(ip)) {
              rtrn = ip;
            } else if (ip_col.getBytes().length === 4) {
              ip = ip_col.getBytes()[0] + \".\" + ip_col.getBytes()[1] + \".\" + ip_col.getBytes()[2] + \".\" + ip_col.getBytes()[3] ;
              rtrn = ip;
            } else if (ip_col.length === 23) {
              ip_col = ip_col.substring(0, 11);
              ip = Packages.com.snc.sw.context.support.net.IPUtils.hex2String(ip_col);
              if (Packages.com.snc.sw.context.support.net.IPUtils.isIPAddress(ip)) {
                rtrn = ip;
              }
            } else rtrn = \"\";
            "}}
          }
        }
      }
    }

Step 13: vip_relation_to_device

Operation: Relation and/or Reference

This step creates a reference between virtual IPs and the load balancer devices in the CMDB. This step creates a relationship and reference between the virtual IPs, and the load balancers in the F5 BIG-IPs [cmdb_ci_lb_bigip] table. The results are put into the vip_device table.

The Relationship type specifies that the virtual IPs run on the load balancer device, while the Direction specifies that the virtual IP is the parent in the relationship.

The load_balancer column is the reference field that is used between the source and target table.

The pattern also specifies that non-matching rows are removed. The "true" Equals "true" condition species that all records should be joined in the table merge.

Settings NDL script equivalent
step {
  name = "vip_relation_to_device"
  relation_reference {
    table1_name = "cmdb_ci_lb_service"
    table2_name = "cmdb_ci_lb_bigip"
    result_table_name = "vip_device"
    unmatched_lines = remove
    condition = contains {
      "true"
      "true"
    }
    relation_type = "Runs on::Runs"
    ref_direction = parentToChild
    ref_field_name = "load_balancer"
  }
}

Step 14: get_pools_snmp

Operation: SNMP query

This step discovers load balancer pools.

Settings NDL script equivalent
NSNM
step {
  name = "get_pools_snmp"
  run_snmp_to_var {
    snmp_object_ids = table {
      name = "1.3.6.1.4.1.3375.2.2.5.1.2.1"
      col_names = "1", "2"
    }
    var_names = table {
      name = "cmdb_ci_lb_pool"
      col_names = "name", "load_balancing_method"
    }
    if_not_found_do = nop {}
  }
}

Step 15: lb_method_var

Operation: Set variable

This step applies a series of name:value pairs to the variable methodString.

Settings NDL script equivalent
Setting the variable
step {
  name = "lb_method_var"
  if {
    condition = contains {
      ""
      ""
    }
    on_true = set_attr {
      "methodString"
      "0:round-robin,1:ratio-member,2:least-connections-member,3:observed-member,4:predictive-member,5:ratio-node,6:least-connections-node,7:fastest-node,8:observed-node,9:predictive-node,10:dynamic-ratio-node,11:fastest-application,12:least-sessions,13:dynamic-ratio-member,14:l3-address,15:weighted-least-connections-member,16:weighted-least-connections-node,17:ratio-session"
    }
    on_false = nop {}
  }
}

Step 16: pools_ref_device

Operation: Relation and/or Reference

This step creates a reference between the load balancer pools and the load balancer devices in the CMDB. The source table is the Load Balancer Pool [cmdb_ci_lb_pool] table, and the target table is the F5 BIG-IPs [cmdb_ci_lb_bigip] table. The results are put into the pools_device table.

The Relationship type specifies that the pool runs on the load balancer device, while the Direction specifies that the pool is the parent in the relationship.

The load_balancer column is the reference field that is used between the source and target table.

The pattern also specifies that non-matching rows are removed. The "true" Equals "true" condition species that all records should be joined in the table merge.

Settings NDL script equivalent
step {
  name = "pools_ref_device"
  relation_reference {
    table1_name = "cmdb_ci_lb_pool"
    table2_name = "cmdb_ci_lb_bigip"
    result_table_name = "pools_device"
    unmatched_lines = remove
    condition = eq {
      "true"
      "true"
    }
    relation_type = "Runs on::Runs"
    ref_direction = parentToChild
    ref_field_name = "load_balancer"
  }
}

Step 17: parse_method_to_table

Operation: Parse variable

This step parses the methodString variable using delimited text. It takes the series of name:value pairs and puts the name into the load_balancing_method variable and the number into the method_number variable.

Settings NDL script equivalent
Figure 3. Parsing a method to a table
Parsing a method to a table
step {
  name = "parse_method_to_table"
  parse_var_to_var {
    from_var_name = "methodString"
    to_var_names = table {
      name = "methods"
      col_names = "method_number", "load_balancing_method"
    }
    parsing_strategy = delimited_parsing {
      delimiters = ":"
      selected_positions = 1, 2
      line_seperator = ","
    }
    if_not_found_do = nop {}
  }
}

Step 18: vip_relation_to_pool

Operation: Relation and/or Reference

This step creates a reference between the virtual IPs and the load balancer pools in the CMDB. The source table is the Load Balancer Service [cmdb_ci_lb_service] table, and the target table is the Load Balancer Pool [cmdb_ci_lb_pool] table. The results are put into the vip_to_pool table.

The Direction specifies that the virtual IP is the parent in the relationship.

The pool column is the reference field that is used between the source and target table. The merge criteria specifies that the name field on the two tables must have the same value.

Settings NDL script equivalent
Creating a reference between a service and a pool
step {
  name = "vip_reation_to_pool"
  relation_reference {
    table1_name = "cmdb_ci_lb_service"
    key1_name = "name"
    table2_name = "cmdb_ci_lb_pool"
    key2_name = "name"
    result_table_name = "vip_to_pool"
    unmatched_lines = remove
    ref_direction = parentToChild
    ref_field_name = "pool"
  }
}

Step 19: get_pools_member_snmp

Operation: SNMP query

This step discovers members of load balancer pools.

Settings NDL script equivalent
Discovering pool members
step {
  name = "get_pools_member_snmp"
  run_snmp_to_var {
    snmp_object_ids = table {
      name = "1.3.6.1.4.1.3375.2.2.5.3.2.1"
      col_names = "3", "4", "1"
    }
    var_names = table {
      name = "cmdb_ci_lb_pool_member"
      col_names = "ip_address", "service_port", "name"
    }
    if_not_found_do = nop {}
  }
}

Step 20: pools_ref_pools_member

Operation: Relation and/or Reference

This step creates a reference between the load balancer pool members and the load balancer pools in the CMDB. The source table is the Load Balancer Pool Member [cmdb_ci_lb_pool_member] table, and the target table is the Load Balancer Pool [cmdb_ci_lb_pool] table. The results are put into the pools_pools_member table.

The Direction specifies that the pool member is the parent in the relationship.

The pool column is the reference field that is used between the source and target table.

The pattern also specifies that non-matching rows are removed. The "true" Equals "true" condition species that all records should be joined in the table merge.

Settings Script equivalent
Creating a reference between a pool members and pools
step {
  name = "pools_ref_pools_member"
  if {
    condition = eq {
      "true"
      "false"
    }
    on_true = relation_reference {
      table1_name = "cmdb_ci_lb_pool_member"
      key1_name = "name"
      table2_name = "cmdb_ci_lb_pool"
      key2_name = "name"
      result_table_name = "pools_pools_member"
      unmatched_lines = remove
      condition = eq {
        "true"
        "true"
      }
      ref_direction = parentToChild
      ref_field_name = "pool"
    }
    on_false = nop {}
  }
}

Step 21: pool_member_ref_device

Operation: Relation and/or Reference

This step creates a reference between the load balancer pool members and the load balancers in the CMDB. The source table is the Load Balancer Pool Member [cmdb_ci_lb_pool_member] table, and the target table is the F5 BIG-IPs [cmdb_ci_lb_bigip] table. The results are put into the pool_member_device table.

The Relationship type specifies that the pool member runs on the load balancer device, while the Direction specifies that the pool member is the parent in the relationship.

The load_balancer column is the reference field that is used between the source and target table.

The pattern also specifies that non-matching rows are removed. The "true" Equals "true" condition species that all records should be joined in the table merge.

Settings Script equivalent
Creating a reference between a pools and load balancers
step {
  name = "pool_member_ref_device"
  relation_reference {
    table1_name = "cmdb_ci_lb_pool_member"
    table2_name = "cmdb_ci_lb_bigip"
    result_table_name = "pool_member_device"
    unmatched_lines = remove
    condition = eq {
      "true"
      "true"
    }
    relation_type = "Runs on::Runs"
    ref_direction = parentToChild
    ref_field_name = "load_balancer"
  }
}