Joe Williams

  • Content Count

  • Joined

  • Last visited

  • Days Won


Community Reputation

9 Neutral

About Joe Williams

  • Rank

Recent Profile Visitors

1,659 profile views
  1. I am trying to get it working currently and not have to much success. I got the non report ones working, minus sharepoint. The Report ones, I configured everything I was told to, but the invoke-webrequest inside of get-graphapi returns nothing for some reason. So it errors out. Did you have any issues similiar?
  2. Yeah, this could be accomplished with ssh or remote powershell. Would just require some extra work in adding manual instances and having proper permissions.
  3. Guessing it hasn't been approved yet. Below is the PowerShell script and the AppliesTo is 'auto.activedatasources =~ "HTTPS"' $URL = "https://" $URL = $URL + "##hostname##" try { [Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} $webRequest = [System.Net.HttpWebRequest]::Create($URL) $webRequest.KeepAlive = $false $webRequest.Timeout = 5000 $webRequest.ServicePoint.ConnectionLeaseTimeout = 5000 $webRequest.ServicePoint.MaxIdleTime = 5000 #$null = $webRequest.GetResponse() $null = $webRequest.GetResponse().Dispose() } catch [System.Net.WebException] { if ($_.Exception.Status -eq [System.Net.WebExceptionStatus]::TrustFailure) { # We ignore trust failures, since we only want the certificate, and the service point is still populated at this point } else { # Write-Warning $_.Exception.Message } } catch { # Write-Warning $_.Exception.Message } if (($webRequest.ServicePoint.Certificate) -and ($webRequest.ServicePoint.Certificate.Handle -ne 0)) { if ($ReturnCertificate) { # Write-Output $webRequest.ServicePoint.Certificate } else { $IssuerCN = $webRequest.ServicePoint.Certificate.Issuer.Split(', ',[System.StringSplitOptions]::RemoveEmptyEntries)[0].Split('=')[1] $SubjectCN = $webRequest.ServicePoint.Certificate.Subject.Split(', ',[System.StringSplitOptions]::RemoveEmptyEntries)[0].Split('=')[1] $ValidFrom = $webRequest.ServicePoint.Certificate.GetEffectiveDateString() $ValidTo = $webRequest.ServicePoint.Certificate.GetExpirationDateString() Write-Host "certificate.IssuerCN=$IssuerCN" Write-Host "certificate.SubjectCN=$SubjectCN" Write-Host "certificate.ValidFrom=$ValidFrom" Write-Host "certificate.ValidTo=$ValidTo" } $webRequest.ServicePoint.Certificate.Dispose() } [Net.ServicePointManager]::ServerCertificateValidationCallback = $null
  4. We had to find out who issued the SSL cert on port 443 for a bunch of network devices and servers. So I wrote this TCPMLH. It pulles the IssuerCN, SubjectCN, ValidFrom and ValidTo info for the certificate. It could easily be modified to look at other ports as well if wanted. It depends on a PropertySource that was listed here awhile ago 'DataSources_List', which I don't have the key for, but can share the XML if needed.
  5. Did it add them into unmonitored? Or just not add them at all?
  6. I might be misunderstanding what you are trying, but why can't you convert the firmware version into a number, and alert on if it changes?
  7. I figured I would share these with anyone who would want them. The first DataSource reaches out to the Datto Portal and gathers info on the BCDR via the Datto portal and utilizing their REST API. It is ATFZGD. As part of this DataSource, it pulls basically all values that are provided and a few complex just to convert KB to GB and get percentages. Active Tickets Agent Count Alert Count Local Storage Available Local Storage Used Offsite Storage Used Share Count The second one pulls the same BCDR devices and gets the backup status from them. It is 2KZEKJ. As part of this DataSrouce, we pull the below info. Also as part of this, we have active discovery set to every hour so the error message for the backup can be used as an auto property, that we can then pull into the alert message. There are 2 complex data points as well. 1 is so archived backups in error don't trigger and another so paused backups in archive don't trigger. Archived Last Backup Status Last Backup Timestamp Last Offsite Last Screenshot Attempt Last Screenshot Attempt Status Last Snapshot Paused Protected Volumes Count Total Local Snapshots Unprotected Volumes Count
  8. Go into Datasources -> Add -> From LogicModule Exchange. Type in that code.
  9. Use the 6477DR code in the LM Exchange. It pulls everything down. I used it and heavily modified it to monitor via VPG instead of VM as each VM is forced to have the same RPO/Status.
  10. It would be nice to be able to clone dashboards via the API. I have an onboarding system I wrote for some of our technicians that creates folders and collector groups and sets specific properties that are required for our ticketing system. It also creates use roles with the specific permissions, etc.... One of the items I want to be able to do is have a Default Dashboard group and list out the dashboards in there. Allowing them to chose which ones they want. For the record I tried to be cheeky and used Developer Tools to see what was being done to clone a dashboard and I can't even use that to get it working. Comes up with 'HTTP Status 415 – Unsupported Media Type'.
  11. Not sure I like this idea. This could be handled in your ticketing system. All alerts have a specific LMID. Send that as well with the ticket create and if the incident is still open/active child or don't create at all.
  12. I am writing a Groovy DataSource for covering some items that aren't there by default for Nimble. I am having issues getting the data to appear properly under the instances I would think it should. Active Discovery is this and it works as expected. import com.santaba.agent.groovyapi.expect.Expect; import com.santaba.agent.groovyapi.snmp.Snmp; import com.santaba.agent.groovyapi.http.*; import com.santaba.agent.groovyapi.jmx.*; import org.xbill.DNS.*; hostname = hostProps.get("system.hostname"); nimuser=hostProps.get("nim.user"); nimpass=hostProps.get("nim.pass"); cli =, nimuser,nimpass) cli.send("ctrlr --list \n\r") cli.expect(/-----/) cli.expect("Nimble OS") commandOutput=cli.before() //We only want the output from after the first header row to end of the command (when the prompt is back) commandOutput.eachLine { if (!(it =~ /-----/) && !(it =~ /Name\s*State\s*Hostname /)) { //ignore table header if (it.startsWith("A") || it.startsWith("B")) { tokens = it.split(); //println it //print tokens[0]; //println "\r\n" controller = tokens[0] controllername = tokens[2] println controller+"##"+controllername } } } cli.send("exit \n\r") cli.expectClose() I then have the below for the main part of the script. It is currently just a POC. I am not grabbing everything I want yet. When I test the script I get back what I want, but no matter what, the instances for the fans do not show up under the Controllers. import com.santaba.agent.groovyapi.expect.Expect; import com.santaba.agent.groovyapi.snmp.Snmp; import com.santaba.agent.groovyapi.http.*; import com.santaba.agent.groovyapi.jmx.*; import org.xbill.DNS.*; hostname = hostProps.get("system.hostname"); nimuser=hostProps.get("nim.user"); nimpass=hostProps.get("nim.pass"); arraydesc = "##WILDALIAS##"; cli =, nimuser,nimpass) cli.send("ctrlr --info ##WILDVALUE## \n\r") cli.expect("Name: ") cli.expect("Nimble OS") commandOutput=cli.before() commandOutput.eachLine // { instance_index, it -> { // println it; if (it.startsWith("\tpower-supply")) { nametokens = it.split(" at "); psname = nametokens[0]; psname = psname.trim(); psname = psname.replace("\t", ""); psdescr = nametokens[1]; psdescr = psdescr.split(":"); psdescr = psdescr[0]; tokens = it.split(": "); psstate = tokens[1]; psstate = psstate.trim(); psstate = psstate.replace("\t", ""); if (psstate == "ok") { psstate = "0"; } else { psstate = "1"; } // println psname+" - "+psdescr+" - "+psstate; } if (it.startsWith("\tfan")) { fannamestoken = it.split(" at "); fanname = fannamestoken[0]; fanname = fanname.trim(); fanname = fanname.replace("\t", ""); fandescr = fannamestoken[1]; fandescr = fandescr.split(" of"); fandescr = fandescr[0]; fandescr = fandescr.trim(); fandescr = fandescr.replace("\t",""); fanstate = it.split(","); fanstate = fanstate[0]; fanstate = fanstate.split(": "); fanstate = fanstate[1]; fanstate = fanstate.trim(); fanstate = fanstate.replace("\t", ""); if (fanstate == "ok") { fanstate = "0"; } else { fanstate = "1"; } fanspeed = it.split("speed: "); fanspeed = fanspeed[1]; fanspeed = fanspeed.trim(); fanspeed = fanspeed.replace("\t", ""); fanspeed = fanspeed.replace("rpm", "") //println fanname+" - "+fandescr+" - "+fanstate+" - "+fanspeed; println "${arraydesc}##${fanname}######" println "auto.nimble_array_fan_description=${fandescr}" println "auto.nimble_array_grouptype=fan" println "${arraydesc}##${fanname}######.Status=${fanstate}"; } } cli.send("exit \n\r") cli.expectClose() When I test the script and choose say the A controller I get this as the output. LabNimble02-A##fan1###### auto.nimble_array_fan_description=front auto.nimble_array_grouptype=fan LabNimble02-A##fan1######.Status=0 LabNimble02-A##fan2###### auto.nimble_array_fan_description=front auto.nimble_array_grouptype=fan LabNimble02-A##fan2######.Status=0 LabNimble02-A##fan3###### auto.nimble_array_fan_description=rear auto.nimble_array_grouptype=fan LabNimble02-A##fan3######.Status=0 LabNimble02-A##fan4###### auto.nimble_array_fan_description=rear auto.nimble_array_grouptype=fan LabNimble02-A##fan4######.Status=0
  13. This is the way I will end up probably going, but was hoping I didn't have to go through all of that. I just wanted to simply clone it.
  14. This is a good idea. I would also tag on and say can we do it for a collector group? So that way when a new collector is added to a specific group, it just inherits the schedule?
  15. Ultimately I will be using PHP, but the above example/code was from Postman. Attached is a screenshot of Postman.