Forum Discussion

Gary_Dewrell's avatar
8 years ago

Rest API and Powershell

So I have had pretty good luck converting the Python examples to Powershell.
The one thing I can not figure out how to do is return volume usage for a specific host.

Anyone got any example powershell script using Rest API to pull volume usage on a host?

 

7 Replies

Replies have been turned off for this discussion
  • Excellent, thank you... progress!  new error... but in a response code :)/emoticons/smile@2x.png 2x" title=":)" width="20">  1401 auth failed... I can work with that.

    <edit> Working now!  I had to refresh all of the variable contents in my ISE session. </edit>

  • I'm working on transitioning some of our custom reporting over from SCOM to LM as we transition.  I'm having a difficult time getting REST to give me anything at all.  I have an API Token created and have saved it into my credential store.  I'm using the CredentialManager 2.0 module to access them.  Here's the rest:

    Import-Module    CredentialManager
    $Cred           = Get-StoredCredential -Target LogicMonitor
    
    $accessId       = $cred.UserName
    $accessKey      = $cred.GetNetworkCredential().Password
    
    $company        = "ourcompany"
    
    $httpVerb       = "GET"
    $resourcePath   = "/device/devices"
    
    $epoch          = [Math]::Round(
        ( New-TimeSpan `
            -start ( Get-Date -Date "1/1/1970"  ) `
            -end   ( Get-Date ).ToUniversalTime() `
        ).TotalMilliseconds
    )
    
    <# Concatenate Request Details #>
    $requestVars    = $httpVerb + $epoch + $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' )
    
    <# Construct URL #>
    $url            = "https://$company.logicmonitor.com/santaba/rest$resourcePath"
    
    <# Make Request #>
    $response       = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $headers

    I'm getting this response:

    Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
    At line:1 char:19
    + ... nse       = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $he ...
    +                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
        + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

    what am I missing here?  All of the parts look right going into the invoke:

    PS C:\Users\cole.mcdonald> $url;$httpVerb;$headers
    https://beyondimpact.logicmonitor.com/santaba/rest/device/devices
    GET
    Key           Value
    ---           -----
    Authorization LMv1 m27K656aHIjt946ST92q:ZGMzNjk5NTIyZDE2YzMyYTBiOTc0MTFiM2U4MGVmOGQyMWNjNGRiOWNmZDJjNjU2Y2VjYjQxNWViOTg2MDI0NQ==:1553558842750
    Content-Type  application/json

    (Moderator: please feel free to move this reply if necessary - Not sure if you want this in a new thread or not.)

  • Sarah_Terry's avatar
    Sarah_Terry
    Icon for Product Manager rankProduct Manager

    Hi Gary - DataSources have two ids: one id for the DataSource template, and another id for each Device-DataSource combinations (for each device it's applied to).  So in this case, 94 is the id of the DataSource itself, but what you want is the id of the DataSource instantiated for device 1.  So in your example, you want the 'id' field (58), which corresponds to the unque device-datasource combination, instead of the dataSourceId field (94).  Additionally, the instances themselves have ids, so you'd need to get the instance id to put in the resource path if you wanted data for one specific instance.  I recommend omitting the instance id from the resource path if you don't mind getting data for multiple instances. So the resource path should be:

    $resourcePath = '/device/devices/1/devicedatasources/58/data'

    Otherwise, you could make a GET request to /device/devices/1/devicedatasources/58/instances to get instance ids.  Does that make sense?

    Thanks,
    Sarah

  • Thank you for your quick response. I feel like I am close.  I wrote code to return the device and datasource info. Here is a sample output:
    id                       : 58
    deviceId                 : 1
    dataSourceId             : 94

    dataSourceName           : WinVolumeUsage-
    dataSourceDescription    : 
    dataSourceDisplayName    : Volume Usage
    graphs                   :  
    overviewGraphs           : 
    groupName                : Disks
    deviceName               : c896-01
    deviceDisplayName        : volta-c896-01
    monitoringInstanceNumber : 2
    instanceNumber           : 2
    instanceAutoGroupEnabled : False
    groupsDisabledThisSource : 
    status                   : 0
    createdOn                : 0
    updatedOn                : 1490145619
    assignedOn               : 1490145552
    nextAutoDiscoveryOn      : 1490231952
    autoDiscovery            : True
    isMultiple               : True
    alertStatus              : none
    alertStatusPriority      : 100000
    sdtStatus                : SDT-none-none
    alertDisableStatus       : none-none-none
    stopMonitoring           : False
    alertingDisabledOn       : 
    sdtAt                    : _hs-customer
    dataSourceType           : DS
     

    From this I believe the 

    $resourcePath = '/device/devices/1/devicedatasources/94/instances/2/data'  should be correct but I get an output of:


    Status:1007
    Response:

     

    What am I missing?

  • Sarah_Terry's avatar
    Sarah_Terry
    Icon for Product Manager rankProduct Manager

    Hi Gary,

    To get volume usage, you'll want to use the data resource: https://www.logicmonitor.com/support/rest-api-developers-guide/data/get-data/

    You'll need the id of the device you want to get volume usage for, and the datasource and instance ids that correspond to volume usage for that device.  Alternatively, you can leave out the instance id if you have multiple volumes you want usage for on the same device.  In PowerShell, the request should look something like this (with the correct ids, of  course):

    <# account info #>
    $accessId = 'YQQ75w6Mxx9zWIeAMq5H'
    $accessKey = 'f)!Z}%spR=6en+4^s2$t32r-3=NpdQ]2T{-deI)8'
    $company = 'apiAccount'
    
    <# request details #>
    $httpVerb = 'GET'
    $resourcePath = '/device/devices/533/devicedatasources/10256/instances/23/data'
    $queryParams = ‘?period=2’
    
    <# Construct URL #>
    $url = 'https://' + $company + '.logicmonitor.com/santaba/rest' + $resourcePath + $queryParams
    
    <# 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 + $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')
    
    <# Make Request #>
    $response = Invoke-RestMethod -Uri $url -Method Get -Header $headers 
    
    <# Print status and body of response #>
    $status = $response.status
    $body = $response.data| ConvertTo-Json -Depth 5
    
    Write-Host "Status:$status"
    Write-Host "Response:$body"

     

    Thanks,

    Sarah