REST API Developer's Guide

Update a Device

You can use LogicMonitor's REST API to update the devices in your account.

As with all of our API calls, authentication is required.

There are two ways to update a device:

  • PUT: A PUT request enables you to replace an entire device definition (and update fields in the process).  You should use PUT to update a device if you want to provide an updated JSON definition for the device.  Note that consistent with REST standards, any properties not specified in a PUT request will revert back to their default values.
  • PATCH: A PATCH request enables you to replace only certain fields for a device.  You should use PATCH if you don't have the JSON definition for the device and you only want to update a few fields.

 

PUT

Note that consistent with REST standards, any properties not specified in a PUT request will revert back to their default values.  As such, you'll want to be sure to include any custom device configuration and/or properties in the request.  One easy way to accomplish this is to first make a GET request for the desired device, manipulate the device's JSON definition, and then use that JSON in a PUT request to update the device (see Example 2 for an example).  Passing an obfuscated property value as eight stars will preserve it's value in LogicMonitor.  Note that we do plan to publish a PATCH method to make this process easier (as HTTP PATCH does not require that you include every parameter in the request).

HTTP Method: PUT

URI: /device/devices/{id}

Request Parameters:

Property

Description

Required?

Type

Example

name The host name or IP address of the device Yes String "name":"10.36.11.240"
displayName The display name of the device Yes String "displayName":"ProdServer24"
preferredCollectorId The Id of the preferred collector assigned to monitor the device Yes Integer "preferredCollectorId":85
hostGroupIds The Id(s) of the groups the device is in, where multiple group ids should be comma separated No. Defaults to "1" (root group). String "hostGroupIds":"2,34"
description The device description No String "description":"A server in the LA Datacenter"
disableAlerting Indicates whether alerting is disabled (true) or enabled (false) for this device No. Defaults to false. Boolean "disableAlerting":false
link The URL link associated with the device No String "link":"https://status.aws.amazon.com"
enableNetflow Indicates whether Netflow is enabled (true) or disabled (false) for the device No. Defaults to false. Boolean "enableNetflow":false
netflowCollectorId The Id of the netflow collector associated with the device If enableNetflow=true Integer "netflowCollectorId":125
customProperties Define custom properties for this device. Each property needs to have a name and a value. No JSON object "customProperties":[{"name":"snmp.version","value":"v3"},{"name":"location","value":"Santa Barbara, CA"}]

 

Example 1: Python PUT

The following Python script updates the device with id 253

#!/bin/env python

import requests
import json
import hashlib
import base64
import time
import hmac

#Account Info
AccessId ='48v2wRzfK94y53sq5EuF'
AccessKey ='H_D9i(f5~B^U36^K6i42=^nS~e75gy382Bf6{)P+'
Company = 'api'

#Request Info
httpVerb ='PUT'
resourcePath = '/device/devices/253'
data = '{"name":"10.36.11.240","displayName":"ProdServer24","preferredCollectorId":90,"hostGroupIds":"2","description":"a server in the LA datacenter"}'

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + data + resourcePath

#Construct signature
signature = base64.b64encode(hmac.new(AccessKey,msg=requestVars,digestmod=hashlib.sha256).hexdigest())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
response = requests.put(url, data=data, headers=headers)

#Print status and body of response
print 'Response Status:',response.status_code
print 'Response Body:',response.content
 

 

The following is an example response for the request above:

Response Status: 200
Response Body: {
  "status" : 200,
  "errmsg" : "OK",
  "data" : {
    "id" : 253,
    "name" : "10.36.11.240",
    "displayName" : "ProdServer24",
    "deviceType" : 0,
    "relatedDeviceId" : -1,
    "currentCollectorId" : 90,
    "preferredCollectorId" : 90,
    "preferredCollectorGroupId" : 1,
    "preferredCollectorGroupName" : "@default",
    "description" : "a server in the LA datacenter",
    "createdOn" : 1458754984,
    "updatedOn" : 1470715583,
    "disableAlerting" : false,
    "autoPropsAssignedOn" : 0,
    "autoPropsUpdatedOn" : 0,
    "scanConfigId" : 0,
    "link" : "",
    "enableNetflow" : false,
    "netflowCollectorId" : 0,
    "netflowCollectorGroupId" : 0,
    "netflowCollectorGroupName" : null,
    "lastDataTime" : 0,
    "lastRawdataTime" : 0,
    "hostGroupIds" : "2",
    "sdtStatus" : "none-none-none",
    "userPermission" : "write",
    "hostStatus" : "normal",
    "alertStatus" : "confirmed-warn-none",
    "alertStatusPriority" : 1100,
    "awsState" : 1,
    "alertDisableStatus" : "none-none-none",
    "alertingDisabledOn" : null,
    "collectorDescription" : "ip-374-32-37-182.us-west-1.compute.internal",
    "netflowCollectorDescription" : null,
    "customProperties" : [ {
      "name" : "system.categories",
      "value" : ""
    } ],
    "upTimeInSeconds" : 0,
    "deletedTimeInMs" : 0,
    "toDeleteTimeInMs" : 0,
    "hasDisabledSubResource" : false,
    "manualDiscoveryFlags" : {
      "winprocess" : false,
      "linuxprocess" : false,
      "winservice" : false
    }
  }
} 

 

Example 2: Groovy PUT

The following Groovy script first makes a GET request to get the JSON definition for device 257, changes the device's preferredCollectorId, and then makes a PUT request with the updated JSON:

import org.apache.http.HttpEntity
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPut
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import groovy.json.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;


//define credentials and url
def accessId = 'YQQ75w6Mxx9zWIeAMq5H';
def accessKey = 'f)!Z}%spR=6en+4^s2$t32r-3=NpdQ]2T{-deI)8';
def account = 'apiAccount';
def resourcePath = "/device/devices/257"
def url = "https://" + account + ".logicmonitor.com" + "/santaba/rest" + resourcePath;

//get current time
epoch = System.currentTimeMillis();

//calculate signature
requestVars = "GET" + epoch + resourcePath;

hmac = Mac.getInstance("HmacSHA256");
secret = new SecretKeySpec(accessKey.getBytes(), "HmacSHA256");
hmac.init(secret);
hmac_signed = Hex.encodeHexString(hmac.doFinal(requestVars.getBytes()));
signature = hmac_signed.bytes.encodeBase64();

// HTTP GET
CloseableHttpClient httpclient = HttpClients.createDefault();
httpGet = new HttpGet(url);
httpGet.addHeader("Authorization" , "LMv1 " + accessId + ":" + signature + ":" + epoch);
response = httpclient.execute(httpGet);
responseBody = EntityUtils.toString(response.getEntity());
code = response.getStatusLine().getStatusCode();

response = new JsonSlurper().parseText(responseBody.toString());
device = response.data;
device.preferredCollectorId = 90;
device = JsonOutput.toJson(device)
StringEntity params = new StringEntity(device,ContentType.APPLICATION_JSON);

epoch = System.currentTimeMillis(); //get current time

requestVars = "PUT" + epoch + device + resourcePath;

// construct signature
hmac = Mac.getInstance("HmacSHA256");
secret = new SecretKeySpec(accessKey.getBytes(), "HmacSHA256");
hmac.init(secret);
hmac_signed = Hex.encodeHexString(hmac.doFinal(requestVars.getBytes()));
signature = hmac_signed.bytes.encodeBase64();

// HTTP PUT
httpPut = new HttpPut(url);
httpPut.addHeader("Authorization" , "LMv1 " + accessId + ":" + signature + ":" + epoch);
httpPut.setHeader("Accept", "application/json");
httpPut.setHeader("Content-type", "application/json");
httpPut.setEntity(params);
responsePut = httpclient.execute(httpPut);
responseBodyPut = EntityUtils.toString(responsePut.getEntity());
codePut = responsePut.getStatusLine().getStatusCode();

// Print Response
println "Status:" + codePut;
println "Response body:" + responseBodyPut;
httpclient.close(); 

 

PATCH

HTTP Method: PATCH

URI: /device/devices/{id}

Request Parameters:

With every PATCH request you must include a query parameter patchFields that indicates which fields should be updated, where multiple fields should be comma separated.  If a field is identified in the patchFields parameter and included in the payload of the request, its value will be updated.  All other field values will remain the same.  E.g. to update a device's name, the URI + query parameter would be /santaba/rest/device/devices/{id}?patchFields=Name.  The name field would also need to be included in the request payload.  The following fields can be updated via PATCH:

Property

Description

Type

Example

name The host name or IP address of the device String "name":"10.36.11.240"
displayName The display name of the device String "displayName":"ProdServer24"
preferredCollectorId The Id of the preferred collector assigned to monitor the device Integer "preferredCollectorId":85
hostGroupIds The Id(s) of the groups the device is in, where multiple group ids should be comma separated String "hostGroupIds":"2,34"
description The device description String "description":"A server in the LA Datacenter"
disableAlerting Indicates whether alerting is disabled (true) or enabled (false) for this device Boolean "disableAlerting":false
link The URL link associated with the device String "link":"https://status.aws.amazon.com"
enableNetflow Indicates whether Netflow is enabled (true) or disabled (false) for the device Boolean "enableNetflow":false
netflowCollectorId The Id of the netflow collector associated with the device Integer "netflowCollectorId":125
customProperties Define custom properties for this device. Each property needs to have a name and a value. To add or update just one or a few device properties in the customProperties object, but not all of them, you'll need to additionally use the opType query parameter. The opType query parameter can be set to add, refresh or replace. opType=add indicates that the properties included in the payload will be added, but all existing properties will remain the same. opType=replace indicates that the properties included in the request payload will be added if they don't already exist, or updated if they do already exist, but all other existing properties will remain the same. opType=refresh indicates that the properties will be replaced with those included in the request payload. JSON object "customProperties":[{"name":"snmp.version","value":"v3"},{"name":"location","value":"Santa Barbara, CA"}]

 

Example 1: Python PATCH

The following python script enables Netflow and sets a Netflow Collector for device 435, but leaves all other device fields as is:

import requests
import json
import hashlib
import base64
import time
import hmac

#Account Info
AccessId ='48v2wRzfK94y53sq5EuF'
AccessKey ='H_D9i(f5~B^U36^K6i42=^nS~e75gy382Bf6{)P+'
Company = 'api'

#Request Info
httpVerb ='PATCH'
resourcePath = '/device/devices/435'
queryParams = '?patchFields=enableNetflow,netflowCollectorId'
data = '{"enableNetflow":true,"netflowCollectorId":85}'

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath +queryParams

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + data + resourcePath

#Construct signature
signature = base64.b64encode(hmac.new(AccessKey,msg=requestVars,digestmod=hashlib.sha256).hexdigest())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
response = requests.patch(url, data=data, headers=headers)

#Print status and body of response
print 'Response Status:',response.status_code
print 'Response Body:',response.content

 

Example 2: Python PATCH

The following python script enables adds a property for device 435, but leaves all other device fields as is:

import requests
import json
import hashlib
import base64
import time
import hmac

#Account Info
AccessId ='48v2wRzfK94y53sq5EuF'
AccessKey ='H_D9i(f5~B^U36^K6i42=^nS~e75gy382Bf6{)P+'
Company = 'api'

#Request Info
httpVerb ='PATCH'
resourcePath = '/device/devices/435'
queryParams = '?patchFields=customProperties&opType=add'
data = '{"customProperties":[{"name":"snmp.version","value":"v2c"}]}'

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath +queryParams

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + data + resourcePath

#Construct signature
signature = base64.b64encode(hmac.new(AccessKey,msg=requestVars,digestmod=hashlib.sha256).hexdigest())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
response = requests.patch(url, data=data, headers=headers)

#Print status and body of response
print 'Response Status:',response.status_code
print 'Response Body:',response.content

 

Example 3: Python PATCH

The following python script updates the Collector id for all devices that have 'prod' in the display name, and leaves all other fields for the devices as is:

#!/bin/env python

import requests
import json
import hashlib
import base64
import time
import hmac

#Account Info
AccessId ='48v2wRzfK94y53sq5EuF'
AccessKey ='H_D9i(f5~B^U36^K6i42=^nS~e75gy382Bf6{)P+'
Company = 'api'

#Request Info
httpVerb ='GET'
resourcePath = '/device/devices'
queryParam = '?filter=displayName~prod'

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath + queryParam

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + resourcePath

#Construct signature
signature = base64.b64encode(hmac.new(AccessKey,msg=requestVars,digestmod=hashlib.sha256).hexdigest())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
response = requests.get(url, headers=headers)

#Parse response
jsonResponse = json.loads(response.content)

#Loop through each device & update Collector Id
for i in jsonResponse['data']['items']:
    deviceId = str(i['id'])

    #Request Info
    httpVerb ='PATCH'
    resourcePath = '/device/devices/'+deviceId
    queryParams ='?patchFields=preferredCollectorId'
    data = '{"preferredCollectorId":85}'

    #Construct URL 
    url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath +queryParams

    #Get current time in milliseconds
    epoch = str(int(time.time() * 1000))

    #Concatenate Request details
    requestVars = httpVerb + epoch + data + resourcePath

    #Construct signature
    signature = base64.b64encode(hmac.new(AccessKey,msg=requestVars,digestmod=hashlib.sha256).hexdigest())

    #Construct headers
    auth = 'LMv1 ' + AccessId + ':' + signature + ':' + epoch
    headers = {'Content-Type':'application/json','Authorization':auth}

    #Make request
    response = requests.patch(url, data=data, headers=headers)