Creating Internal Collection
Dynamic Applications

Download this manual as a PDF file

The following sections describe how to create and use create Internal Collection Dynamic Applications (ICDAs).

Use the following menu options to navigate the SL1 user interface:

  • To view a pop-out list of menu options, click the menu icon ().
  • To view a page containing all of the menu options, click the Advanced menu icon ().

This section includes the following topics:

Viewing the List of ICDAs

You can view all Internal Collection Dynamic Applications on the Dynamic Applications Manager page (System > Manage > Applications) by typing "Internal" in the Type filter-while-you-type field:

Image of Dynamic Applications Manager page for Internal type

 To ensure the consistency of your data, do not use an ICDA to collect data on a device that was previously monitored by another type of Dynamic Application.

Creating an ICDA

You can create custom Internal Collection Dynamic Applications (ICDAs) to gather data on devices that do not support SNMP. Currently, ICDAs support only the snippet protocol.

If you create an ICDA with a Data Model of Interface Inventory and the ICDA includes a discovery Collection Object, the ICDA aligns with the device after the platform discovery runs. As a result, SL1 does not discover interfaces until either the nightly discovery runs or the user re-discovers the device manually by running the discovery session again, creating a new discovery session, or initiating an ad hoc discovery.

To create an ICDA:

  1. Go to the Dynamic Applications Manager page (System > Manage > Applications).

  1. Click the Actions button and select Create New Dynamic Application. The Dynamic Applications Create New Application page appears.

Image of the Create New Dynamic Application page

  1. Complete the following fields:
  • Application Name. Type a name for this ICDA.
  • Application Type. Your options for ICDAs include Internal Collection Inventory or Internal Collection Performance.

  1. Click the Save button. The Properties tab updates to show the relevant fields for the ICDA:

Image of the ICDA Properties tab

  1. In the Execution Environment drop-down list, select the execution environment to which you want to align the Dynamic Application. An execution environment is an on-demand Python environment that includes the supporting modules, code, scripts, directories, and files (packaged in one or more ScienceLogic Libraries) needed to run a snippet. An execution environment includes its own installation directories, doesn't share libraries with other environments, and allows granular control of dependencies, versions, and permissions. The default execution environment is System. For more information, see the section on Managing Execution Environments.
  2. In the Data Model drop-down list, select the type of data you want to collect with this ICDA. The values in the drop-down are dependent on the value in the Application Type field. The value in the Data Model field list determines the available options in the Object Link drop-down list on the Collections tab. For example, if you select Availability for the Data Model, then you can choose only Availability or Latencyin the Object Link drop-down list.
  • If you selected Internal Collection Inventory as the Application Type, the Data Model drop-down includes:
  • Filesystem Inventory. Monitors Storage Size, Filesystem Type, Storage Used, Storage Units, or Media Type.
  • Interface Inventory. Monitors Name, Alias, Description, Type, Physical Address, Speed, High Speed, Admin Status, Operational Status, Connector Present, 64-bit Support, Blade, Port, or IP Address.
  • If you selected Internal Collection Performance as the Application Type, the Data Model drop-down includes:
  • Availability. Monitors Availability or Latency.
  • Filesystem Performance. Monitors Storage Used, Storage Units, or Percentage Used.
  • SNMP Detail. Monitors System Description, System Uptime, or System Locale.
  • Interface Performance. Monitors Octets In, Octets Out, Errors In, Errors Out, Discards In, Discards Out, Physical Address, Admin Status, or Operational Status.
  1. Update the remaining fields as needed, and then click the Save button.
  2. Next, create a container for your ICDA snippet code.

Creating a Container for the ICDA Snippet

In Snippet Dynamic Applications, each collection object must be associated with a snippet. Therefore, in ICDAs you must create the container for the snippet code before creating the collection objects for this ICDA.

To create a container for the snippet code:

  1. Click the Snippets tab.

Image of the Snippets tab for a new ICDA

  1. Complete the following fields:
  • Snippet Name. The name of the snippet.
  • Active State. Specifies whether the snippet should be executed by SL1 when performing collection for the ICDA.
  • Required. Specifies whether this snippet is required for successful collection of all other snippet requests. Choices are:
  • Required - Stop Collection. If this snippet request fails, the platform will not attempt to execute any other snippet requests in this ICDA. Dynamic Applications that consume the cache of this ICDA will halt collection.
  • Not Required - Continue Collection. If this snippet request fails, the platform will continue executing all remaining snippet requests in this ICDA. Dynamic Applications that consume the cache of this ICDA will continue collection.
  • Snippet Code. The python code that will be executed when SL1 performs collection for this ICDA. You will add the snippet code later.
  1. Click the Save button.
  2. Repeat this process for each collection you want to use in conjunction with a snippet.
  3. Next, create the collection objects for your ICDA.

Creating the Collection Objects

To create the collection object or objects for this ICDA:

  1. Click the Collections tab.

Image of the Collections tab for an ICDA

  1. Complete the following fields to create the collection object:
  • Object Name. Type the name of the collection object.
  • Snippet Arguments. Specify any arguments you want to pass to the snippet.
  • Class Type. Depending on the type of collection object you want to create, select [33] ICDA Object or [100] Discovery.
  • String Type. Define the string type for this snippet. Select Standard or Hex Code.
  • Object Link. Select the specific type of data you want to collect with this ICDA. The options in this drop-down list are based on your selection for the Data Model field on the Properties tab.
  • Snippet. Select the name of the snippet you created in the previous process.
  1. Update the remaining fields as needed, and then click the Save button.
  2. Repeat these steps to create additional collection objects you want to use in conjunction with a snippet.
  3. Next, add the snippet code for your new ICDA.

Adding the Snippet Code

To add the snippet code to a new ICDA:

  1. Click the Snippets tab.
  2. In the Snippet Registry pane, select the relevant snippet and click its wrench icon (). Information about that snippet appears in the top pane:

Image of the Snippets tab

  1. In the Snippet Code field, type or paste your python code for the collection object.
  2. Click the Save button and close the modal page for the ICDA.

Snippet Examples for ICDAs

The following snippets were created by ScienceLogic to use as sample snippets for ICDAs.

Availability

from silo_builtin_caching import get_cached_request_result

Windows_Server_Uptime_REQ_GUID = '32CA377A59190A6AB83DC5EDB05CA7E7'

result = {

'if': get_cached_request_result(self, Windows_Server_Uptime_REQ_GUID)

}

print "********************************************************"

print result

 

for grp_id, grp in self.oids.iteritems():

for obj_id, obj in grp.iteritems():

try:

(req, oid) = obj['oid'].split('.')

result_list = result[req].get(oid, {}).values()

 

except ValueError:

self.logger.ui_debug('Skipping OID %d' % obj_id)

continue

if len(result_list) >= 1 and float(result_list[0]) > 0.0:

obj['result'] = [(0, True)]

 

#obj['result'] = [(0, True if len(result_list) >= 1 and float(result_list[0]) > 0.0 else False)]

print obj

 

Discovery

from silo_common.global_definitions import CRED_SSH

import paramiko

if self.cred_details['cred_type'] == CRED_SSH:

host = self.cred_details['cred_host']

user = self.cred_details['cred_user']

passwd = self.cred_details['cred_pwd']

timeout = self.cred_details['cred_timeout'] / 1000

port = self.cred_details['cred_port']

 

ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

 

ssh.connect(host, username=user, password=passwd, port=port, timeout=timeout)

stdin, stdout, stderr = ssh.exec_command("uname")

os = stdout.readlines()

if os[0].startswith("Linux"):

result_handler['disc'] = True

ssh.close()

else:

self.logger.debug("ICDA Filesystem | DID %s: Incorrect credential type aligned, must be SSH" % self.did)

 

Filesystem Inventory

from silo_builtin_caching import get_cached_request_result

import re

 

#Enum to translate drive type to string

FS_ENUM_TYPES={

0: 'Unknown',

1: 'No Root Directory',

2: 'Removable Disk',

3: 'Local Disk',

4: 'Network Drive',

5: 'Compact Disc',

6: 'RAM Disk'

}

 

result = get_cached_request_result(self, WINDOWS_SERVER_DISK_CONFIGURATION_REQ_GUID)

indexes = set()

units_object = {}

 

for grp_id, grp in self.oids.iteritems():

for obj_id, obj in grp.iteritems():

oid = obj['oid']

result_list = result.get(oid, {}).items()

 

#Keep track of all the indexes (which are the filesystem names)

#Rewrite the results list to clean up filesystem names

for (i, (k, v)) in enumerate(result_list):

#An empty string index will attempt to use the label first,

#and fall back to " " if there is no label

if k == '':

k = result.get('label',{}).get('',' ')

result_list[i] = (k, v)

#Add a backslash to drive letters to match the output from SNMP

elif re.match('[A-Z]:$', k):

k += '\\'

result_list[i] = (k, v)

indexes.add(k)

 

#If this is the 'units' object, set it aside for later processing

if obj['oid'] == 'units':

units_object = obj

continue

 

#Translate the drivetype enum to a string

if obj['oid'] == 'drivetype':

result_list = [(index, FS_ENUM_TYPES.get(int(value), value)) for index, value in result_list]

 

obj['result'] = result_list

 

#Do the processing for the units object (all units are 1 - bytes)

units_object['result'] = [(i, 1) for i in indexes]

Filesystem Type

from silo_common.global_definitions import CRED_SSH

import paramiko

if self.cred_details['cred_type'] == CRED_SSH:

host = self.cred_details['cred_host']

user = self.cred_details['cred_user']

passwd = self.cred_details['cred_pwd']

timeout = self.cred_details['cred_timeout'] / 1000

port = self.cred_details['cred_port']

 

ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.connect(host, username=user, password=passwd, port=port, timeout=timeout)

 

stdin, stdout, stderr = ssh.exec_command("df --output=target,fstype", timeout=timeout)

 

results = []

lines = stdout.readlines()[1:]

for line in lines:

fs_name, fs_type = map(lambda line: line.strip(), line.split(' ', 1))

results.append((fs_name, fs_type))

result_handler['fs_type'] = results

ssh.close()

else:

self.logger.debug("ICDA Filesystem | DID %s: Incorrect credential type aligned, must be SSH" % self.did)

 

Interface Octets

from silo_common.credentials import snmph_from_cred_array

from silo_common.exceptions import SnmpError

OID_ifInOctets = '.1.3.6.1.2.1.2.2.1.10'

results = []

try:

snmp_h = snmph_from_cred_array(self.cred_details, self.ip)

octets_in_walk = snmp_h.walk(OID_ifInOctets)

 

for oid, value in octets_in_walk:

if_index = oid.split('.')[-1]

# offset to make this differentiable from the value returned by normal internal collection

if_in_octets = int(value) + 100000

results.append((if_index, if_in_octets))

except SnmpError, err:

self.logger.ui_debug("An SNMP error occurred during interface performance collection")

finally:

result_handler['ifInOctets'] = results

 

Latency

from silo_collect.tools import latency_ping

from silo_common.network import ip

ip_obj = ip(self.ip)

# add large offset to make ICDA data stand out

result_handler['latency'] = [('0', latency_ping(ip_obj, logger=self.logger) + 5000)]