Recent Discussions
Duplicate interfaces being discovered while doing any IOS upgrade on devices.
Duplicate interfaces being discovered while doing any IOS upgrade on devices. Initially as per support we did some fine tuning on data source level, however recently this issue becomes more severe as we have lot of hardware changes planned. Anyone came across this issue or any solution for it? I know whenever any hardware changes happen there could be interface index value changes but we have 2-3 duplicate value of interfaces and we have to carefully disabled the one which does not have any data considering historical data.rana41515 days agoNeophyte76Views0likes1CommentNOC Rollup Status Dashboards for MSPs
LM doesn't come with it out of the box, so I built the NOC Dashboard I've wanted. It provides high level, at-a-glance health indicators for each of our client environments we manage. This makes a great "big board" for a NOC room or a second screen status board for work from home NOC/Support folks. I do have three examples in this code for ways to filter for specific teams/purposes. This all collapses for ease of reference correctly in Powershell ISE on windows. Line 282 references a dataSource I wrote that counts frequency of specific eventlog events to illustrate potential brute force attempts (CTM are my initials, we tag our scripts to make finding the best source of answers faster in the future - old habit from pen & paper change logs from a previous job). As any screenshots would contain client names, I'm unable to post any screen shots of the results of this, but my current settings for my Main dashboard are (This is the first Dashboard I've made that looks better in UIv4 than 3): ... #!!! These two need to be changed. First is a string, second an integer #!!! See the comment block below for instructions # The first chunk of your company's logicmonitor URL $company = "yourCompanyNameHere" # ID of the group to be used as a source for the NOC widget items $parentGroupID = <parentGroupID> <# Netgain Technology, llc ( https://netgaincloud.com ) 2/26/2024 - Developed by Cole McDonald Disclaimer: Neither Netgain nor Cole McDonald are not responsible for any unexpected results this script may cause in your environment. To deploy this: - COLLECTOR: you will need a collector for scripting, this will be the single applies to target. You may need to increase the script timeout depending on the size of your device deployment. - DASHBOARD: you will need a Dashboard with a NOC widget on it. The name can be whatever you'd like, there will be a name change in the "name" property for the initial array. In the case of the first example here, "NOC - Master" - PARENT GROUP: you will need to identify the ID# of the group you wish to use as the source for the subgroup list and set the $parentGroupID to the appropriate ID# Purpose: Create an auto-updating high level NOC dashboard that can show - Rollup state for a list of client subgroups from our \Clients group - Group Indicators for a specific dataSource - Group indicators for a subset of devices within each group After the API region, there are three separate dashboards referenced to illustrate the 3 methods for using this dataSource. NOTE: my code uses backticks for line continuation. Where possible in my code, each line indicates a single piece of information about the script's algorithm and the first character in each line from a block indicates the line's relationship to the one above it. #> #region Rest API Initialization and Functions # Init variables used in the RESTApi functions $URLBase = "https://$company.logicmonitor.com/santaba/rest" $accessID = "##ApiAccessID.key##" $accessKey = "##ApiAccessKey.key##" #-------- The Functions ---------- function Send-Request { param ( $cred , $URL , $accessid = $null, $accesskey = $null, $data = $null, $version = '3' , $httpVerb = "GET" ) if ( $accessId -eq $null) { exit 1 } <# Use TLS 1.2 #> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 <# Get current time in milliseconds #> $epoch = [Math]::Round( ( New-TimeSpan ` -start (Get-Date -Date "1/1/1970") ` -end (Get-Date).ToUniversalTime()).TotalMilliseconds ) <# Concatenate Request Details #> $requestVars = $httpVerb + $epoch + $data + $resourcePath <# Construct Signature #> $hmac = New-Object System.Security.Cryptography.HMACSHA256 $hmac.Key = [Text.Encoding]::UTF8.GetBytes( $accessKey ) $signatureBytes = $hmac.ComputeHash( [Text.Encoding]::UTF8.GetBytes( $requestVars ) ) $signatureHex = [System.BitConverter]::ToString( $signatureBytes ) -replace '-' $signature = [System.Convert]::ToBase64String( [System.Text.Encoding]::UTF8.GetBytes( $signatureHex.ToLower() ) ) <# Construct Headers #> $auth = 'LMv1 ' + $accessId + ':' + $signature + ':' + $epoch $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add( "Authorization", $auth ) $headers.Add( "Content-Type" , 'application/json' ) # uses version 2 of the API $headers.Add( "X-version" , $version ) <# Make Request #> $response = Invoke-RestMethod ` -Uri $URL ` -Method $httpVerb ` -Body $data ` -Header $headers ` -erroraction SilentlyContinue ` -warningaction SilentlyContinue Return $response } function Get-LMRestAPIObjectListing { param ( $URLBase , $resourcePathRoot , # "/device/devices" $size = 1000 , $accessKey , $accessId , $version = '2' ) $output = @() $looping = $true $counter = 0 while ($looping) { #re-calc offset based on iteration $offset = $counter * $size $resourcePath = $resourcePathRoot $queryParam = "?size=$size&offset=$offset" $url = $URLBase + $resourcePath + $queryParam # Make Request $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -version $version if ( $response.items.count -eq $size ) { # Return set is full, more items to retrieve $output += $response.items $counter++ } elseif ( $response.items.count -gt 0 ) { # Return set is not full, store date, end loop $output += $response.items $looping = $false } else { # Return set is empty, no data to store, end loop $looping = $false } } write-output $output } # Get Dashboards $resourcePath = "/dashboard/dashboards" $dashboards = Get-LMRestAPIObjectListing ` -resourcePathRoot $resourcePath ` -accessKey $accessKey ` -accessId $accessID ` -URLBase $URLBase # Get Widgets $resourcePath = "/dashboard/widgets" $widgets = Get-LMRestAPIObjectListing ` -resourcePathRoot $resourcePath ` -accessKey $accessKey ` -accessId $accessID ` -URLBase $URLBase # Get Groups $resourcePath = "/device/groups" $Groups = Get-LMRestAPIObjectListing ` -resourcePathRoot $resourcePath ` -accessKey $accessKey ` -accessId $accessID ` -URLBase $URLBase #endregion function generateJSON { param( $dashInfo, $clientnames, $deviceDisplayName = "*", $DSDisplayName = "*" ) $itemArray = @() foreach ($name in $clientnames) { $itemArray += @{ "type" = "device" "deviceGroupFullPath" = "Clients/$name" "deviceDisplayName" = $deviceDisplayName "dataSourceDisplayName" = $DSDisplayName "instanceName" = "*" "dataPointName" = "*" "groupBy" = "deviceGroup" "name" = "`#`#RESOURCEGROUP`#`#" } } # Write JSON back to the API for that widget $outputJSON = "`n`t{`n`t`t`"items`" : [`n" foreach ($item in $itemArray) { $elementJSON = @" { `"type`" : `"$($item.type)`", `"dataPointName`" : `"$($item.dataPointName)`", `"instanceName`" : `"$($item.instanceName)`", `"name`" : `"$($item.name)`", `"dataSourceDisplayName`" : `"$($item.dataSourceDisplayName)`", `"groupBy`" : `"$($item.groupBy)`", `"deviceGroupFullPath`" : `"$($item.deviceGroupFullPath)`", `"deviceDisplayName`" : `"$($item.deviceDisplayName)`" } "@ if ($item -ne $itemArray[-1]) { $outputJSON += "$elementJSON,`n" } else { # Last Item $outputJSON += "$elementJSON`n`t`t]`n`t}" } } write-output $outputJSON } # Get Client Names from groups $clientnames = ( $groups ` | where parentid -eq $parentGroupID ` | where name -notmatch "^\." ).name | sort #ID Master Dashboard # declare dashboard name and set default id and widgetid to use in the loop later $masterDash = @{ id=0; widgetid=0; name="NOC - Master" } $master = $dashboards | ? name -eq $masterDash.name if (($master.name).count -eq 1) { $masterDash.id = $master.id $masterDash.widgetid = $master.widgetsConfig[0].psobject.Properties.name $outputJSON = generateJSON ` -dashInfo $masterDash ` -clientnames $clientnames $resourcePath = "/dashboard/widgets/$($masterDash.widgetid)" $url = $URLBase + $resourcePath $widget = Send-Request ` -accessKey $accessKey ` -accessId $accessID ` -data $outputJSON ` -URL $URL ` -httpVerb "PATCH" } #ID Network Dashboard # declare dashboard name and set default id and widgetid to use in the loop later $networkDash = @{ id=0; widgetid=0; name="NOC - Network" } # preset filters for specific dashboard targeting by device $networkDeviceDisplayNameString = "*(meraki|kemp)*" $network = $dashboards | ? name -eq $networkDash.name if (($network.name).count -eq 1) { $networkDash.id = $network.id $networkDash.widgetid = $network.widgetsConfig[0].psobject.Properties.name $outputJSON = generateJSON ` -dashInfo $networkDash ` -clientnames $clientnames ` -deviceDisplayName $networkDeviceDisplayNameString $resourcePath = "/dashboard/widgets/$($networkDash.widgetid)" $url = $URLBase + $resourcePath $widget = Send-Request ` -accessKey $accessKey ` -accessId $accessID ` -data $outputJSON ` -URL $URL ` -httpVerb "PATCH" } #ID Security Dashboard # declare dashboard name and set default id and widgetid to use in the loop later $securityDash = @{ id=0; widgetid=0; name="NOC - Security" } # preset filters for specific dashboard targeting by datasource $securityDataSourceDisplayNameString = "Event Frequency Sec:4625 CTM" $security = $dashboards | ? name -eq $securityDash.name if (($security.name).count -eq 1) { $securityDash.id = $security.id $securityDash.widgetid = $security.widgetsConfig[0].psobject.Properties.name $outputJSON = generateJSON ` -dashInfo $securityDash ` -clientnames $clientnames ` -DSDisplayName $securityDataSourceDisplayNameString $resourcePath = "/dashboard/widgets/$($securityDash.widgetid)" $url = $URLBase + $resourcePath $widget = Send-Request ` -accessKey $accessKey ` -accessId $accessID ` -data $outputJSON ` -URL $URL ` -httpVerb "PATCH" }235Views2likes5CommentsLeast Privilege's script to set permissions on Services for Non Admin account.
With the new security push for us to use non admin accounts. If anyone would like I to have a script that can run on Domain and one for Workgroup Servers. That iterates though all services and applies correct SDDL for least privilege's account. Extract these to c:/temp, add your list of servers (or for the workgroup add the single server to the serverlist.txt) and then run the RunScript.ps1 You'll need a local admin account to run with for Workgroup Server You'll need a DA account to run for list of Domain Servers. PM me if you are interested ;)SolvedBarb13 days agoAdvisor141Views2likes4CommentsMonitoring EMR Paragon
We have many different EMR systems that our Facilities use in their business. One of them is the EMR Paragon. One of the items that we found to be helpful is to monitor certain Window Directories for the existence of any files that are more than a few minutes old. That would mean that something may be broken that is not picking up those files and passing them to another business process. Is there an existing monitor of this type of action already in existence? Would you be willing to share that code? Thanks for sharing a method to do this test. There are many directories that need to be tested and we need to create this in a general manner so we can do these checks.Henry_Steinhaue2 months agoNeophyte18Views3likes1CommentCisco Info PropertySources
This one goes into some additional detail but hasn't been completely cleaned up for debugging purposes. The ones that have switch stacks pull all the stack serials and model numbers. Work in progress was the versioning. We have about 1500+ network devices across many many different models and versions so this has taken a little bit of work to get to work across all. MWXMXZ - Cisco-IOS FKA79M - Cisco IOS XE 9LF63N - NXOS G366DD - Cisco ASA213Views2likes14CommentsHP Aruba 6000 switch Support?
Good Afternoon, It seems that the newest switch chassis from Aruba/HP Isn't playing too nicely with LM at the moment. The same DataSources that were useful for the previous HP Switches don't appear to work for the newer 6000 series devices (we have a 6000 and a few 6500s) specifically, the Memory snmp query seems to poll no data - luckily the default CPU for SNMP does work. Has anyone run into this themselves?Jordan-Eil2 months agoNeophyte46Views1like1CommentLM Logs ingestion alerting
We recently had an issue where a host was spewing tons of logs to LM. We fixed the problem but would now like to setup some kind of alerting that would alert us if this happens again. I noticed the Module: LogicMonitor_Collector_LMLogs and that its already in use by our Windows Collectors. I see a few promising Normal Data points: lmLogMessagesAddedToQueueRaw (count of syslog messages sent to Ingest API) and lmLogMessagesSentToIngestRaw (count of log source messages sent to ingest) and SyslogMessagesReceivedRaw (Number of syslog messages received by collector). Then there are some Complex Datapoints that look promising. The problem with all of this is while the Module is in use by one or more of our collectors I am not able to see the graphs or raw data from the Module so I can best determine which data point to use and what the threshold should be. Where can I see the collected data?systemgeek2 months agoNeophyte39Views2likes1CommentDatapoints configuration Discussion
Hello Team, I am trying to create a custom datasource to check the service status. It retrieves a list of services from the host properties(auto.service.names), connects to the host using SSH, checks the status of each service using the systemctl command, and outputs the results. Active Discovery Script: 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.*; // Get the service names from the host property def serviceNames = hostProps.get("auto.service.names") ?: "" def serviceArray = serviceNames.split(",").collect { it.trim() } // SSH details for connecting to the host host = hostProps.get("system.hostname") user = hostProps.get("ssh.user") pass = hostProps.get("ssh.pass") port = hostProps.get("ssh.port")?.toInteger() ?: 22 cert = hostProps.get("ssh.cert") ?: '~/.ssh/id_rsa' timeout = 15000 // Timeout in milliseconds // Initialize JSCH for SSH connection import com.jcraft.jsch.JSch def getServiceStatus(serviceName) { def command = "systemctl is-active ${serviceName}" return getCommandOutput(command).trim() } def getCommandOutput(String input_command) { def output = "" def session = null def channel = null try { def jsch = new JSch() if (user && !pass) { jsch.addIdentity(cert) } session = jsch.getSession(user, host, port) session.setConfig("StrictHostKeyChecking", "no") session.setTimeout(timeout) if (pass) { session.setPassword(pass) } session.connect() channel = session.openChannel("exec") channel.setCommand(input_command) def commandOutput = channel.getInputStream() channel.connect() output = commandOutput.text } finally { if (channel) { channel.disconnect() } if (session) { session.disconnect() } } return output } // Output each service with its status serviceArray.each { serviceName -> def status = getServiceStatus(serviceName) println "${serviceName}##${serviceName}##Status: ${status}" } return 0 Collection Script: Below, I am trying to use the ##WILDVALUE## from the active discovery script to collect the service status value. com.jcraft.jsch.JSch // Initialize JSCH for SSH connection // SSH details for connecting to the host host = hostProps.get("system.hostname") user = hostProps.get("ssh.user") pass = hostProps.get("ssh.pass") port = hostProps.get("ssh.port")?.toInteger() ?: 22 cert = hostProps.get("ssh.cert") ?: '~/.ssh/id_rsa' timeout = 15000 // Timeout in milliseconds // Function to retrieve the service status def getServiceStatus(serviceName) { def command = "systemctl is-active ${serviceName}" def result = getCommandOutput(command) return result?.trim() } // Function to execute command and retrieve output def getCommandOutput(String command) { def output = "" def session = null def channel = null def reader = null try { def jsch = new JSch() if (user && !pass) { jsch.addIdentity(cert) } session = jsch.getSession(user, host, port) session.setConfig("StrictHostKeyChecking", "no") session.setTimeout(timeout) if (pass) { session.setPassword(pass) } session.connect() channel = session.openChannel("exec") channel.setCommand(command) channel.setInputStream(null) channel.setErrStream(System.err) reader = new BufferedReader(new InputStreamReader(channel.getInputStream())) channel.connect() def line while ((line = reader.readLine()) != null) { output += line + "\n" } // Ensuring the channel finishes before disconnecting while (!channel.isClosed()) { Thread.sleep(100) } } catch (Exception e) { println "Error executing command: ${e.message}" } finally { reader?.close() channel?.disconnect() session?.disconnect() } return output } // Retrieve the current service name based on ##WILDVALUE## def serviceName = datasourceinstanceProps.values().collect { it.wildvalue }.find { it != null } if (serviceName) { def status = getServiceStatus(serviceName) def statusValue = (status == "active") ? 1 : 0 println "Service:${serviceName} Status:${statusValue}" return statusValue } else { println "Error: No service name found for ##WILDVALUE##." return null } I need help creating the datapoint to collect service status value. Thanks in advance. The error I am currently getting: param prefix is not invalid in format - (valid_prefixes=[datacollector.], method=namevalue, param=datacollector)Hshukla3 months agoNeophyte70Views4likes2Comments