How risky are PropertySource updates?
I have a user request that I think I can do, but I have some property sources I want to update in order to better accomplish it. I might not have to, but I want to work through updating some and handling the impact. I was looking at Microsoft_SQLServer_Connections, we have version 1.7.0 but latest is 1.25.0. So I grabbed the script source code for the new version, made my own new datasource with AppliesTo being false but with that script code, the 1.25.0, and saved it. Then I could go into edit mode without saving it and change the appliesTo back to match the 1.7.0 installed version we have, so that I could run tests against a bunch of our servers to see the differences. In most cases, I get exactly the same results and properties back, auto.mssqlserver.mssql_url and auto.sql_server_instances. But the new version code in my FAKE unsaved property source also gives back auto.mssql_edition and auto.mssql_version. Which would be fine, a couple of more properties seems fine, and in the dozen or so I checked, the ones the old and new have in common gave me the same results. But I found a couple of servers where the 1.7.0 set a property auto.sql_browser_running, but the new version I'm testing does NOT. This makes me a little nervous because there are a TON of LogicModules, and some of them rely on the Microsoft_SQLServer_Connections PropertySource. So I'm concerned that by doing the update, I could lose some auto property that some other LogicModule may need. I've avoided keeping lots of Property and Data Sources updated because were were already behind when I inherited portal admin, and because under the hood "updates" are really delete/replace. So I guess my HIGH level TL;DR question is, how RISKY or DISASTROUS (heh) have you found it to be, when updating Property Sources? Thanks.44Views0likes2CommentsPropertySource best practices auto vs custom
I looked at our portal and the Exchange for PropertySource modules that might have a lot of the "universal" snmp OIDs because we want to pull some in for all snmp devices. Specifically sysLocation (.1.3.6.1.2.1.1.6.0) for starters. I didn't see one so I plan to make my own. But if there is some Official PropertySource I should know about, but overlooked, let me know. But, assuming I'll be making my own, what would be the best practices for a near-universal PropertySource (isDevice() and hasCategory("snmp"))? Should it be a custom property or an auto property? aka mycompany.sysLocation vs auto.mycompany.sysLocation ? On the one hand, I think custom is made for such purposes, but given that I intend to make it "universal" and given that lots of teams use custom properties however they want (so it isnt as tidy a section as it could be) my gut level desire is to make it an auto property because I know that nobody else can set that on the portal but me, so I can guarantee some consistency. Thoughts? And thank you!Solved53Views2likes2CommentsCreating a propertySource to populate a NOC widget in a dashboard... need ## in a string.
The NOC widget items have a field that requires me to have the string"##RESOURCEGROUP##" pushed through the JSON into the NOC Item…since I’m using a propertySource to run the script on a schedule (I have a larger VM with a collector with a longer script timeout just for doing deeper scripted work through the API or Full Domain sweep types of things that will take more time), The LM System is going to try to replace that at run time rather than returning the explicit string. Who knows the correct escape sequence for turning that into a string literal on its way into the RestApi Patch? Scripting questions through support is best effort, and I don’t usually come with easy questions.Solved124Views11likes5CommentsAutomatic removal of category
We have a piece of software that ran as a service we used to monitor. To make sure the dataSources were pointed correctly, we have a propertySource that adds a category. We’ve since moved away from and uninstalled that software, but the category persists. We have a few other cases as well, servers that were migrated from Azure into our dataCenter that are still tagged as AzureVM, etc. Has anyone found a good way to automatically remove a category or does this remain a manual process?Solved74Views5likes2CommentsDataSources_List PropertySource
(Edit, October 2020 - see later comment below for a version that does all this without needing an API call) Q: What does it do? A: Calls the LogicMonitor API and finds, for each applicable device, a list of DataSource Names that exist on the Device, i.e. have at least one instance. This also includes ConfigSources active on the Device. These are put together as a semicolon-seperated list in the property auto.activedatasources: Q: Why? I can just look at the Device in the Device tree. A: You can, but... This PropertySource means you can create Dynamic Groups and Device Inventory Reports based on the presence or absence of *any* combination of DataSources on Devices. Q: Can you give me a real-world example of this being useful? A: Yes. On a MicrosoftSQL server, LogicMonitor will find the SQL Services via WMI, but the actual SQL Server metrics are found via Perfmon or JDBC methods. If we can't access Perfmon or JDBC for any reason (required services not running, lack of credentials, etc) we'll be missing the SQL stats but quite probably getting all the other Windows metrics (via WMI). This can be very difficult to spot if you have one affected SQL server out of 1,000. With this PropertySource running, you could create a Dynamic Group with a custom query of: auto.ActiveDataSources =~ "WinSQLServices-" && auto.ActiveDataSources !~ "WinSQLServer-"&& auto.ActiveDataSources !~ "WinSQLServer_JDBC-" This will list all the devices on which we've found SQL Services but have failed to find any SQL metrics. Similarly Exchange Services are discovered via WMI, whilst most Exchange metrics come from Perfmon. Or, maybe you want to create a Group to contain all your Linux servers that are running Apache web server andMySQL: isLinux() &&auto.ActiveDataSources =~ "Apache-" &&auto.ActiveDataSources =~ "Mysql-" You will need: A REST API Access ID and Access Key for a user with permissions to at least view all Devices within the account (or all Devices in whichever Groups you wish to consider). These should be set as properties 'apiaccessid.key' and 'apiaccesskey.key' within the Devices tree (generallythe root level,or a Group level if appropriate). The PropertySource will use these to find the list of DataSources present onthe Device, and create theauto.activedatasources property for all devices. auto.activedatasources will have one of two error messages if the required API details are not present or do not give sufficient access to query the Device; this could of course also be used to create Dynamic Groups and in Device Inventory Reports. Note that DataSources are listed by their (unique) 'Name' rather than their (not necessarily unique) 'Displayed As' string seen in the Device tree. v1.0.0:ZLTDWM Current limitations: The auto.property fields are limited to 2,000 characters, so if the list of DataSource Names exceeds this size, the data will be truncated. This is likely to be an edge case only seen on test Devices with multiple custom DataSources applied. Auto Properties are updated daily or when Active Discovery is run for a Device, so there may (will!) be a time lag between DataSources being applied to a Device and those DataSources appearing in this auto.activedatasources property list.153Views3likes19CommentsUse a Property Source to find dead devices
This is a PropertySourcewhich 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 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 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);502Views0likes10Comments