Remove multiple devices from a static group
I want to delete multiple devices from a static group in bulk. i DO NOT want to delete the device itself.
I am new to LogicMonitor but have figured out how to get all members of a group using the API. I just haven't figured out how to then remove all of those devices from that group. Has anyone been successful in doing this?
Justin Dietz
Posted 4 years ago·Last reply 4 years ago
22 comments
Justin Dietz
OP4 years agoAlso to bring this back full circle. This all started because in my folder structure I had a Static Group which contained dynamic Groups under it and there were also resources in that upper level static Group. I only wanted the dynamic folders to remain, and I did not want the 30 resources in the Static Group any longer. Using the UI my options were to either "Manage" each device and choose delete, or click each device then on INFO tab click the "X" on the group I wanted to remove it from (this option however refreshes my screen and takes me away from that group, so then you need to navigate back to the folder you were just at...I hate this feature of the UI). So with this script below you put in the Group ID # that has the resources you want to remove. It gets all the resources and then loops through to PATCH the hostGroupIds property. This is obviously use at your own risk however it does work for me. Running this took about 10-15 seconds to remove all 30 resources from my static group.
## Enter the group you would like to have resources removed from
## This script will take all resources in that group (folders excluded) and remove the resources from that group
$group = "437"
<# Use TLS 1.2 #>
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
<# account info #>
$accessId = ''
$accessKey = ''
$company = ''
<# request details #>
$httpVerb = 'GET'
#use this for a specific Device
$resourcePath = "/device/groups/$group/devices"
<# 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')
$headers.Add("X-Version", "2")
<# Make Request #>
$response = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $headers
<# Print status and body of response #>
$status = $response.status
$body = $response.data| ConvertTo-Json -Depth 5
$devicePayload = $response.items
##loop through each device and remove group from its hostGroupIds property
Foreach ($d in $devicePayload)
{
#find where the group is and remove it from the string along with comma depending on placement
if ($d.hostGroupIds -like "*,$group*")
{
$remove = "," + $group
$groups = $d.hostGroupIds.Replace("$remove","")
}
Else
{
$remove = $group + ","
$groups = $d.hostGroupIds.Replace("$remove","")
}
$httpVerb = 'PATCH'
$id = $d.id
$resourcePath = "/device/devices/$id"
$queryparams = '?patchFields=hostGroupIds'
$data = "{" + '"hostGroupIds":"' + $groups + '"}'
# 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 + $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')
$headers.Add("X-Version", "2")
# Make Request #
$response = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $headers -Body $data
}
Justin Dietz
OP4 years agoFigured out my issue. For anyone who reviewed this and looks at this in the future Mike was right the group Ids are a string and need in quotes....and i was missing the "-Body $data" parameter/value in Invoke-RestMethod.
Mike Moniz
·4 years agoI'm not able to test LM API stuff right now but I suggest trying a few things. Try using other types of calls like POST, PUT and DELETE. Verify capitalization of JSON properties, they are case sensitive. Try using one of the LogicMonitor PowerShell modules from PSGallery to see if they work. They might also be a good source for example code.
Justin Dietz
OP4 years agoGot no where with support. Basically was told they don't support custom scripts. Didn't get any answer why same auth headers work fine with GET but an authentication failed with PATCH
Justin Dietz
OP4 years agoThanks. That has now brought me back to
Going to contact support. GET is working just fine out of postman so my creds have to be correct. I also added X-Version to my GET api call and it works. and I am an Admin in the instance so not sure why i am getting this 1401.
The LM documentation suggests it is something with how the signature is being constructed but I would assume auth should work the same for GET or PATCH
LM User
·4 years agoI think that error has to do with you not specifying v2 in the X-Version header. In Postman, go to the Headers tab and add one called "X-Version" and for the value, put 2.
Justin Dietz
OP4 years agoI was able to get PostMan set up and working for a GET. Hitting an issue with PATCH trying to add a group like you said you successfully done earlier. So what I switched was obviously my method from GET to PATCH. I then added Params and Body. Can you tell me if you see what I am entering wrong?
LM User
·4 years agoFWIW: i didn't have to use 'patchFields=hostGroupIds'. I just used '?fields=hostGroupIds'.
You're also not specifying v2 of the API and that might be the root of the problem. Patch isn't available in v1 of the API IIRC. You can specify v2 by either adding v=2 as a query parameter or add an 'X-Version' header with a value of 2.
Here's the PS that PostMan gives me (i'm not a Posh guy, so see what you can make of it):
Justin Dietz
OP4 years agotested with Quotes and get same "authentication failed" response.
as far as the signature I am just going off what I found in the documentation. REST API v1 Examples | LogicMonitor
I can explore PS modules i suppose. Was hoping to figure this out though. Honestly can't believe there isn't an easy UI way to mass remove devices from a Static group.
LM User
·4 years agoThat's true. It's a string.
LM User
·4 years agoIs your signature only including the access key? There's more that needs to go into that signature.
Mike Moniz
·4 years agoI can't test it but I believe you need to put quotes around the group ids (it's a string). Example '{"hostGroupIds":"2,34,56"}'
Since you are using PowerShell, you may also want to check out some of the unofficial LM PowerShell modules others have created in the PowerShell Gallery that might it easier.
Justin Dietz
OP4 years agoJust installed Postman. Never used it before so will work through figuring that out. script I'm using is below and i was working off what is on this page Update a Device | LogicMonitor
device ID is defined in the $ID variable
LM User
·4 years agoI recommend using Postman to get your API call working properly, then move it into a script. Separates problems with the API from problems with your script.
That said, what does your call look like (no creds)? Are you including the payload body in the calculation of your LMv1 signature (the encrypted part of your LMv1 token)?
Justin Dietz
OP4 years agothanks for the information.
Trying to use the hostGroupIds that you showed me but now running into a new issue.
When I run my PATCH (using powershell btw) i get an errmsg response "Authentication Failed". using same API token i use in my GET (successfully). and I am an Administrator in our LM instance, so the Authentication Failed is really throwing me off here........
LM User
·4 years agoThat's correct. You also can't modify auto properties or inherited properties. Only custom properties can be edited via the api. To change auto properties, you have to modify the propertysource that set them. To modify inherited properties, you have to change group membership.
Mike Moniz
·4 years agoYeah, there is a few means of "properties" when using the LM API. There is LogicMonitor properties like system.hostname and location, then there is properties in the JSON sense like id, name, displayName, etc. When using the API, start looking at the json-properties before looking into the LM-properties like systemProperties and customProperties. Also I believe you can't modify any of the systemProperties via the API except for system.categories.
It still helps to still reference the LMv1 API documentation. You should still actually use the v2 API but its automated Swagger documentation can be limited imho which the v1 docs can help fill in.
Justin Dietz
OP4 years agoand is there any chance you can post a screenshot and blank out creds and stuff so I can see your syntax? if not i understand
Justin Dietz
OP4 years agoWhere are you finding "hostGroupIds". When I get a response from one device i found "deviceGroupIds" in system properties. That is the value i was messing with. Am i looking in the wrong spot?
LM User
·4 years agoYep, @Mike Monizhas the right answer.
I just did this in Postman through the API. Make sure you do a few things:
1. Set the query parameter "fields" to "hostGroupIds"
2. Set the body to include the new overall value of hostGroupIds. In my case, the existing value was "261,260,258". I changed it to "261,260,258,262".
If you're looking for a way to easily do it through the UI, I don't think there is in the way you're hoping. The closest you can get is by navigating to the info tab for the group. On the right, there's a "Groups/Devices" section. Click the trash can next to each one you want to delete.
Mike Moniz
·4 years agoIf you want to ultimately delete the group, you should be able to delete the group with devices in it and LM will prompt if you want to delete just the group (and subgroups) or the group+devices. But test that first. From the API I believe you can send send a PATCH request to /device/devices/{id} and change the hostGroupIds property to exclude the group id you want to remove it from.