Sign in to follow this  
Jeff.Woeber

Use a Property Source to find dead devices

Recommended Posts

This is a PropertySource which runs with active discovery and adds the property auto.lmstatus to the device properties with the current Hoststatus value.  It does this using the REST API and It works great with Dynamic grouping, for example if you wanted to know which device in your portal were currently in a dead status you could create a dynamic group with the applies to of “auto.lmstatus=="dead".  One advantage to using a property source is if the device comes back on-line, Active Discovery will immediately run and change the property to "normal" removing the device from the group.  A copy of the PropertySource is at the bottom of the post.  

Let’s walk through the groovy script.  

Define the account information

This is polling the device properties.  I recommend setting this at the group level so they are inherited to the devices.  

an example of the properties would be

api.user = 5kCPqLgY4DGYP27uw2hc

api.pass = ye[$3y7)_4g6L6uH2TC72k{V6HBUf]Ys+9!vB)[9    *note, any property with .pass in the name will not have visible data.  

api.account = lmjeffwoeber

//Account Info
def accessId = hostProps.get("api.user");
def accessKey = hostProps.get("api.pass");
def account = hostProps.get("api.account");

Define the Query.  We just need the HostSatatus for the device the script is running on.  

def queryParams = '?fields=hostStatus&filter=displayName:'+hostName;
def resourcePath = "/device/devices"

Next we build the URL for the API.  

def url = "https://" + account + ".logicmonitor.com" + "/santaba/rest" + resourcePath + queryParams;

This next part builds the security and runs the API.  It can pretty much be copy\pasted into any groovy scripts that use the REST API.

//get current time
epoch = System.currentTimeMillis();

//calculate signature
requestVars = "GET" + epoch + resourcePath;

hmac = Mac.getInstance("HmacSHA256");
secret = new SecretKeySpec(accessKey.getBytes(), "HmacSHA256");
hmac.init(secret);
hmac_signed = Hex.encodeHexString(hmac.doFinal(requestVars.getBytes()));
signature = hmac_signed.bytes.encodeBase64();

// HTTP Get
CloseableHttpClient httpclient = HttpClients.createDefault();
httpGet = new HttpGet(url);
httpGet.addHeader("Authorization" , "LMv1 " + accessId + ":" + signature + ":" + epoch);
response = httpclient.execute(httpGet);
responseBody = EntityUtils.toString(response.getEntity());
code = response.getStatusLine().getStatusCode();

The API will return a JSON payload.  We use  the Groovy Slurper to transfer the payload to respose_obj were we can use the data.  
 

// user groovy slurper
json_slurper = new JsonSlurper();
response_obj = json_slurper.parseText(responseBody);

They JSON will look like
 

data=[total:1, items:[[hostStatus:dead]]

We can use the value with response_obj.data.items[0].hostStatus.value

Now we print the Key=Value for the property source

//print output
println "LMStatus=" +response_obj.data.items[0].hostStatus.value;
httpclient.close();

This will add the property source "auto.lmstatus" to the device

finally we return 0 do indicate a success.  

return (0);

This is how the PropertySource will appear on the device

JbHMCJc.jpg

 

Lastly, we can create Dynamic Groups based off the Hostatus.  For example use an applies to auto.lmstatus=="dead" to group all of the dead devices into one group, or auto.lmstatus=~"dead" to also include Dead-Collector

qLIbraN.jpg

 

LMStatus PropertySource

import org.apache.http.HttpEntity
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;import com.santaba.agent.groovyapi.http.*;
import groovy.json.JsonSlurper;
	
def hostName = hostProps.get("system.displayname");

//Account Info
def accessId = hostProps.get("api.user");
def accessKey = hostProps.get("api.pass");
def account = hostProps.get("api.account");
data = ''
def queryParams = '?fields=hostStatus&filter=displayName:'+hostName;
def resourcePath = "/device/devices"
def url = "https://" + account + ".logicmonitor.com" + "/santaba/rest" + resourcePath + queryParams;

//get current time
epoch = System.currentTimeMillis();

//calculate signature
requestVars = "GET" + epoch + resourcePath;

hmac = Mac.getInstance("HmacSHA256");
secret = new SecretKeySpec(accessKey.getBytes(), "HmacSHA256");
hmac.init(secret);
hmac_signed = Hex.encodeHexString(hmac.doFinal(requestVars.getBytes()));
signature = hmac_signed.bytes.encodeBase64();

// HTTP Get
CloseableHttpClient httpclient = HttpClients.createDefault();
httpGet = new HttpGet(url);
httpGet.addHeader("Authorization" , "LMv1 " + accessId + ":" + signature + ":" + epoch);
response = httpclient.execute(httpGet);
responseBody = EntityUtils.toString(response.getEntity());
code = response.getStatusLine().getStatusCode();

// user groovy slurper
json_slurper = new JsonSlurper();
response_obj = json_slurper.parseText(responseBody);

//print output
println "LMStatus=" +response_obj.data.items[0].hostStatus.value;
httpclient.close();

return (0);

 

Edited by Jeff.Woeber

Share this post


Link to post
Share on other sites

@Jeff.Woeber that's very cool!

One minor tweak, the 'def hostName' line:

def hostName = hostProps.get("system.displayname");

...should be:

def hostName = java.net.URLEncoder.encode(hostProps.get("system.displayname"));

...to cope with spaces and other non-URL-friendly characters that are permitted in device display names.

:) 

 

Share this post


Link to post
Share on other sites

This is great, just implemented. 

Using for another feature as well in a dynamic group. We have at several times where we'll take major site outages that have 100+ devices, the collectors go a little bonkers with the failed task rates, so we can disable all the datasources and any existing alerts when the device goes dead. Added feature :) 

I noticed you're using the hostStatus, maybe we could also use the alertStatus as well, break it up, and say what the highest state of alert the device is as well? Does active discovery run when a device changes alert state as well? Or just when it goes from dead to normal? 

Edited by Tom Lasswell
  • Like 1

Share this post


Link to post
Share on other sites

Anthony,

I just applied added this as a PropertySource, specified a group of servers, and ran the script test. It succeeded, but applied the properties to 0 devices, even though there are roughly 500 devices, several of which are dead. Any suggestions to where I could be going wrong?

Share this post


Link to post
Share on other sites

@Beau Breeden are you getting any property source applied? on a non-dead device you should still see a property source get attached. If it's working at all, you should see a property source added to each device "LMStatus=" saying alive or dead. If it's not working likely it's your API.user and API.pass keys that are incorrect and make sure you set the API.account as well to your subdomain. 

Share this post


Link to post
Share on other sites
Guest
You are commenting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this