Cole McDonald

Members
  • Content Count

    46
  • Joined

  • Last visited

  • Days Won

    2

Community Reputation

3 Neutral

About Cole McDonald

  • Rank
    Community Whiz Kid

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Cole McDonald

    Increase when idleInterval alerts

    If you don't want to change the event timing itself, you can add a blank line to the Escalation chain... it will use the escalation interval on that blank step which will add time. We use this for Services restarting that take a long time. We need to know that they've restarted, but also need to know if they don't finish restarting. So we have an escalation chain just for the service alerts that alert our team, then waits 20 more minutes before alerting us again. If you add a blank to the end of the escalation chain, you can stop repeated messaging as well. Works especially well if you are using a ticketing system that only accepts email as an incoming connector.
  2. Cole McDonald

    Datasource to poll for number of files in a UNC path?

    You can do this fairly easily with a powershell: $path = '\\##system.displayname##\path\to\count' (get-childitem $path).count If you need different paths / system, you'll have to provide a hash table of those relationships somewhere. Either as a text file on a server accessible from the Collector, the collector itself, or hardcoded into the DataSource. It will need to come in as a "Gauge" value rather than a counter.
  3. Cole McDonald

    Swagger Doc help adding a customProperty to a device

    Thank you. The part I found confusing mostly was the example code given... it is just a generic, blank JSON block. Had that had more detail, I'd have been able to figure it out more quickly. When I've done documentation for Functions and Objects in the past, I've always made sure to include expected input and output... not just types, but structural so that anyone can drop in on my code and be able to produce results immediately. Most of what I've done in the past has been internal tooling, so I saw it as cost savings for the company I was working for due to reduced dev time. I don't tend to see that level of documentation for APIs elsewhere. All of MS's dev docs miss this as well. I've commented on it and they've stated that it was a common complaint. Their new documentation is much clearer, but most of their offerings are still the old documentation style; just giving the function names and leaving it to the developer to parse their meaning/usage.
  4. Cole McDonald

    Collapse Clustered Instances at Group Level

    Previous had an issue with the properties it was adding. If you're creating a new property from a proertySource script, it adds it as an "auto.*" property, which goes away as soon as the script stops processing. To add a new permanent custom property, you have to use the REST API, not just a "category.name=data" output from the script. Here's the final: # These first two lines will need to change to fit your environment. # The groupParentID is the id of a group to house the dynamic groups that will be created... # if that's you root level, use that ID. # We're using a group named "Failover Clusters" in our heirarchy to house them. ####### # Cole McDonald - Sr. Technical Analyst # cole.mcdonald@beyondimpactllc.com # Beyond Impact 2.0, llc # No warranty provided for this code, use at your own risk ####### $company = "Your_Company_Name" $groupParentID = "566" $URLRoot = "https://$company.logicmonitor.com/santaba/rest" $server = "##system.displayname##" $accessID = "##LogicMonitor.accessId.key##" $accessKey = "##LogicMonitor.accessKey.key##" function Send-Request { param ( $cred, $accessid = $null, $accesskey = $null, $URL , $data = $null, $version = '2' , $httpVerb = "GET" ) if ( $accessId -eq $null) { $accessId = $cred.UserName $accessKey = $cred.GetNetworkCredential().Password } # 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 $result = $response Return $result } if ( test-path "\\$server\C`$\Windows\Cluster\CLUSDB" ) { "system.categories=ClusterMember" $clusterInfo = invoke-command ` -ComputerName $server ` -scriptBlock { Import-Module failoverclusters $cluster = get-cluster "$($cluster.name):$($cluster.id)" } $clustername = ($clusterinfo -split ':')[0] $clusterid = ($clusterinfo -split ':')[1] $groupName = "Failover Cluster - $clustername" # Read Groups # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Make Request $response = Send-Request ` -accessid $accessID ` -accesskey $accessKey ` -URL $url $group = $response.items | ? name -eq $groupName if ( ($group | measure-object).count -gt 0 ) { # "*** Group Already exists. Need Device properties? ***" try { $resource = "##Failover.Cluster.GUID##" } catch { $resource = $null } if ( $resource -ne $clusterid ) { # Add Properties # Construct URL $resourcePath = "/device/devices/##system.deviceid##/properties/" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"type`" : `"custom`" , `"name`" : `"Failover.Cluster.GUID`" , `"value`" : `"$ClusterID`" } "@ $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST" } } else { # "*** create group & tag resource ***" # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"name`" : `"$groupName`" , `"parentId`" : `"$groupParentID`" , `"disableAlerting`" : `"true`" , `"enableNetflow`" : `"false`" , `"appliesTo`" : `"Failover.Cluster.GUID == \`"$ClusterID\`"`" , `"customProperties`" : [{ `"name`" : `"Failover.Cluster.ParentGUID`" , `"value`" : `"$ClusterID`" }] } "@ try { $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST" # Add Properties # Construct URL $resourcePath = "/device/devices/##system.deviceid##/properties/Failover.Cluster.GUID" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"type`" : `"custom`" , `"name`" : `"Failover.Cluster.GUID`" , `"value`" : `"$ClusterID`" } "@ $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "PUT" } catch { $error[0] | out-file $logPath -append } } }
  5. Cole McDonald

    more cluster alert improvement requests

    Previous had an issue with the properties it was adding. If you're creating a new property from a proertySource script, it adds it as an "auto.*" property, which goes away as soon as the script stops processing. To add a new permanent custom property, you have to use the REST API, not just a "category.name=data" output from the script. Here's the final: # These first two lines will need to change to fit your environment. # The groupParentID is the id of a group to house the dynamic groups that will be created... # if that's you root level, use that ID. # We're using a group named "Failover Clusters" in our heirarchy to house them. ####### # Cole McDonald - Sr. Technical Analyst # cole.mcdonald@beyondimpactllc.com # Beyond Impact 2.0, llc # No warranty provided for this code, use at your own risk ####### $company = "Your_Company_Name" $groupParentID = "566" $URLRoot = "https://$company.logicmonitor.com/santaba/rest" $server = "##system.displayname##" $accessID = "##LogicMonitor.accessId.key##" $accessKey = "##LogicMonitor.accessKey.key##" function Send-Request { param ( $cred, $accessid = $null, $accesskey = $null, $URL , $data = $null, $version = '2' , $httpVerb = "GET" ) if ( $accessId -eq $null) { $accessId = $cred.UserName $accessKey = $cred.GetNetworkCredential().Password } # 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 $result = $response Return $result } if ( test-path "\\$server\C`$\Windows\Cluster\CLUSDB" ) { "system.categories=ClusterMember" $clusterInfo = invoke-command ` -ComputerName $server ` -scriptBlock { Import-Module failoverclusters $cluster = get-cluster "$($cluster.name):$($cluster.id)" } $clustername = ($clusterinfo -split ':')[0] $clusterid = ($clusterinfo -split ':')[1] $groupName = "Failover Cluster - $clustername" # Read Groups # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Make Request $response = Send-Request ` -accessid $accessID ` -accesskey $accessKey ` -URL $url $group = $response.items | ? name -eq $groupName if ( ($group | measure-object).count -gt 0 ) { # "*** Group Already exists. Need Device properties? ***" try { $resource = "##Failover.Cluster.GUID##" } catch { $resource = $null } if ( $resource -ne $clusterid ) { # Add Properties # Construct URL $resourcePath = "/device/devices/##system.deviceid##/properties/" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"type`" : `"custom`" , `"name`" : `"Failover.Cluster.GUID`" , `"value`" : `"$ClusterID`" } "@ $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST" } } else { # "*** create group & tag resource ***" # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"name`" : `"$groupName`" , `"parentId`" : `"$groupParentID`" , `"disableAlerting`" : `"true`" , `"enableNetflow`" : `"false`" , `"appliesTo`" : `"Failover.Cluster.GUID == \`"$ClusterID\`"`" , `"customProperties`" : [{ `"name`" : `"Failover.Cluster.ParentGUID`" , `"value`" : `"$ClusterID`" }] } "@ try { $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST" # Add Properties # Construct URL $resourcePath = "/device/devices/##system.deviceid##/properties/Failover.Cluster.GUID" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"type`" : `"custom`" , `"name`" : `"Failover.Cluster.GUID`" , `"value`" : `"$ClusterID`" } "@ $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "PUT" } catch { $error[0] | out-file $logPath -append } } }
  6. Cole McDonald

    Swagger Doc help adding a customProperty to a device

    with out the stray }] … and the properties are case sensitive!
  7. Cole McDonald

    Swagger Doc help adding a customProperty to a device

    Thank you Joe, looks like the JSON was the part I had wrong! This worked for making the new property and populating it: $resourcePath = "/device/devices/2332/properties/" $url = $URLRoot + $resourcePath $data = ` @" { `"type`" : `"custom`" , `"name`" : `"Failover.Cluster.GUID`" , `"value`" : `"$ClusterID`" }] } "@ $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST"
  8. Can anyone translate the Swagger Doc into something I can understand? I'm looking specifically at the device properties PUT or PATCH to try to figure out how to add a customProperty to a device. Here's what I've got (PowerShell): # Construct URL $resourcePath = "/device/devices/2332/properties/CustomProperties" $url = $URLRoot + $resourcePath $data = ` @" { `"customProperties`" : [{ `"name`" : `"Failover.Cluster.ParentGUID`" , `"value`" : `"$ClusterID`" }] } "@ $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "PUT" Send-Request handles all of the encryption and the invoke-restmethod {}
  9. Cole McDonald

    Cloning Dashboard Groups With Rest

    yeah... I always just assume I'm going to have to build it by hand... not just Logic Monitor, everything. It's in my DNA though, I started programming when, if you wanted software that did a specific thing, you had to write it. (back in the punch card and teletype days).
  10. Cole McDonald

    Cloning Dashboard Groups With Rest

    Forgive me if you have already tried and discounted this for whatever reason, but my first thought is to 1) GET the json for the current "Template" using the rest API to get the entirety of its definition 2) Change the JSON to match the changes you need made to that (customer name, team name, project name) 3) POST the changed JSON to make the new group 4) Build a recursive function to walk that hierarchy 5) Grab each of the dashboards and change the appliesto to match the new set of devices a)I'm currently doing that piece with a token at the directory level for each of our customers that I can then just change at the dashboard group level to make a full dashboard suite for them. 6) Duplicate each of those to the new dashboard group, and change the token.
  11. Cole McDonald

    Cloning Dashboard Groups With Rest

    What platform / scripting language?
  12. Cole McDonald

    more cluster alert improvement requests

    I completed my dynamic cluster discovery: # Change this to match the ID of your parent folder for your clusters $groupParentID = "566" # Change this to your company name from your LM URL $company = "your_company_name" $URLRoot = "https://$company.logicmonitor.com/santaba/rest" $server = "##system.displayname##" $accessID = "##LogicMonitor.accessId.key##" $accessKey = "##LogicMonitor.accessKey.key##" function Send-Request { param ( $cred, $accessid = $null, $accesskey = $null, $URL , $data = $null, $version = '2' , $httpVerb = "GET" ) if ( $accessId -eq $null) { $accessId = $cred.UserName $accessKey = $cred.GetNetworkCredential().Password } # 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 $result = $response Return $result } if ( test-path "\\$server\C`$\Windows\Cluster\CLUSDB" ) { "system.categories=ClusterMember" $clusterInfo = invoke-command ` -ComputerName $server ` -scriptBlock { Import-Module failoverclusters $cluster = get-cluster "$($cluster.name):$($cluster.id)" } $clustername = ($clusterinfo -split ':')[0] $clusterid = ($clusterinfo -split ':')[1] $groupName = "Failover Cluster - $clustername" # Read Groups # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Make Request $response = Send-Request ` -accessid $accessID ` -accesskey $accessKey ` -URL $url $group = $response.items | ? name -eq $groupName if ( ($group | measure-object).count -gt 0 ) { # "*** Group Already exists. Need Device properties? ***" try { $resource = "##Auto.Failover.Cluster.GUID##" } catch { $resource = $null } if ( $resource -ne $clusterid ) { # Add Properties "Failover.Cluster.GUID=$clusterid" } } else { # "*** create group & tag resource ***" # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"name`" : `"$groupName`" , `"parentId`" : `"$groupParentID`" , `"disableAlerting`" : `"true`" , `"enableNetflow`" : `"false`" , `"appliesTo`" : `"Auto.Failover.Cluster.GUID == \`"$ClusterID\`"`" , `"customProperties`" : [{ `"name`" : `"Auto.Failover.Cluster.ParentGUID`" , `"value`" : `"$ClusterID`" }] } "@ try { $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST" } catch { $error[0] | out-file $logPath -append } # Add Properties "Failover.Cluster.GUID=$clusterid" } }
  13. Cole McDonald

    Collapse Clustered Instances at Group Level

    Done!!! Here's the final code... same warnings as in my previous post: $company = "beyondimpact" $URLRoot = "https://$company.logicmonitor.com/santaba/rest" $groupParentID = "566" $server = "##system.displayname##" $accessID = "##LogicMonitor.accessId.key##" $accessKey = "##LogicMonitor.accessKey.key##" function Send-Request { param ( $cred, $accessid = $null, $accesskey = $null, $URL , $data = $null, $version = '2' , $httpVerb = "GET" ) if ( $accessId -eq $null) { $accessId = $cred.UserName $accessKey = $cred.GetNetworkCredential().Password } # 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 $result = $response Return $result } if ( test-path "\\$server\C`$\Windows\Cluster\CLUSDB" ) { "system.categories=ClusterMember" $clusterInfo = invoke-command ` -ComputerName $server ` -scriptBlock { Import-Module failoverclusters $cluster = get-cluster "$($cluster.name):$($cluster.id)" } $clustername = ($clusterinfo -split ':')[0] $clusterid = ($clusterinfo -split ':')[1] $groupName = "Failover Cluster - $clustername" # Read Groups # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Make Request $response = Send-Request ` -accessid $accessID ` -accesskey $accessKey ` -URL $url $group = $response.items | ? name -eq $groupName if ( ($group | measure-object).count -gt 0 ) { # "*** Group Already exists. Need Device properties? ***" try { $resource = "##Auto.Failover.Cluster.GUID##" } catch { $resource = $null } if ( $resource -ne $clusterid ) { # Add Properties "Failover.Cluster.GUID=$clusterid" } } else { # "*** create group & tag resource ***" # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"name`" : `"$groupName`" , `"parentId`" : `"$groupParentID`" , `"disableAlerting`" : `"true`" , `"enableNetflow`" : `"false`" , `"appliesTo`" : `"Auto.Failover.Cluster.GUID == \`"$ClusterID\`"`" , `"customProperties`" : [{ `"name`" : `"Auto.Failover.Cluster.ParentGUID`" , `"value`" : `"$ClusterID`" }] } "@ try { $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST" } catch { $error[0] | out-file $logPath -append } # Add Properties "Failover.Cluster.GUID=$clusterid" } }
  14. Cole McDonald

    Collapse Clustered Instances at Group Level

    OK... I've got everything working but the folder creation... isolating and fixing.
  15. Cole McDonald

    Collapse Clustered Instances at Group Level

    Alright... I'm really close. What am I missing here? It worked, then it didn't... now it applies the first output and stops doing the rest of them. I know it's something small and dumb, but I've been staring at this for a while now: Disclaimer: Neither I nor Beyond Impact 2.0, LLC make any warrantee that this code will work properly in your environment. Use cautiously. Caveat Emptor. # appliesTo: isWIndows() $server = "##system.hostname##" # change the company name and groupParentID # This is a manually created folder for holding the dynamic cluster groups. Your ID may Vary. $groupParentID = "566" $company = "Your_Company_Name" $URLRoot = "https://$company.logicmonitor.com/santaba/rest" # I added these at the top level of our heirarchy so everything I write has access to them. # -- For the REST API calls -- $accessID = "##LogicMonitor.accessId.key##" $accessKey = "##LogicMonitor.accessKey.key##" function Send-Request { param ( $cred, $accessid = $null, $accesskey = $null, $URL , $data = $null, $version = '2' , $httpVerb = "GET" ) if ( $accessId -eq $null) { $accessId = $cred.UserName $accessKey = $cred.GetNetworkCredential().Password } # 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 $result = $response Return $result } # *** Look for the Windows Failover Cluster DB *** if ( test-path "\\$server\C`$\Windows\Cluster\CLUSDB" ) { "system.categories=ClusterMember" $clusterInfo = invoke-command ` -ComputerName $server ` -scriptBlock { Import-Module failoverclusters $cluster = get-cluster "$($cluster.name):$($cluster.id)" } $clustername = ($clusterInfo -split ':')[0] $clusterid = ($clusterInfo -split ':')[1] $groupName = "Failover Cluster - $clustername" # *** Read Groups *** # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Make Request $response = Send-Request ` -accessid $accessID ` -accesskey $accessKey ` -URL $url $group = $response.items | ? name -eq $groupName if ( ($group | measure-object).count -gt 0 ) { # "*** Group Already exists. Need Device properties? ***" try { $resource = "##Failover.Cluster.GUID##" } catch { $resource = $null } if ( $resource -ne $clusterid ) { # Add Properties "Failover.Cluster.GUID=$clusterid" } } else { # "*** create group & tag resource ***" # Construct URL $resourcePath = "/device/groups" $url = $URLRoot + $resourcePath # Construct Data Body $data = ` @" { `"name`" : `"$groupName`" , `"parentId`" : `"$groupParentID`" , `"disableAlerting`" : `"true`" , `"enableNetflow`" : `"false`" , `"appliesTo`" : `"Failover.Cluster.GUID == \`"$ClusterID\`"`" , `"customProperties`" : [{ `"name`" : `"Failover.Cluster.ParentGUID`" , `"value`" : `"$ClusterID`" }] } "@ $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -data $data ` -httpVerb "POST" # *** Verify GUID is stored in the device info *** try { $resource = "##Failover.Cluster.GUID##" } catch { $resource = $null } if ( $resource -ne $clusterid ) { # Add Properties "Failover.Cluster.GUID=$clusterid" } } }