Forum Discussion

WillFulmer's avatar
WillFulmer
Icon for Neophyte rankNeophyte
7 years ago

Bulk rename/append name of devices

I have opened a support ticket - #94980. I would like to request the ability to group rename or modify the naming of devices.

Specifically, I want to add all devices under 'Client A' and append the DNS suffix clientdomain.com to the name of all devices.

I would like to do this so that when an engineer is working on Server X, they can see it clearly as ServerX.clientdomain.com.

Ticket is to programatically do this vs. manually renaming each device.

Support ticket and engineer attempted this using Rest APIs with no luck

"As same as at property source,  system.displayname is special and cannot be changed through RestAPI as well."
Rest of thing we can do now is to submit a feature request to change the current design "propertysource can change auto property only"


 

 

Thanks
WIll

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

    Hi @WillFulmer,

    This is possible with our REST API.  The implementation will be quite similar to Example 3 on this page: https://www.logicmonitor.com/support/rest-api-developers-guide/devices/update-a-device/ (which iterates through all devices that meet a certain criteria and changes their preferred Collector). The only changes you need to make to the script are: (1) you'll instead want to set the filter such that only devices in the group Client A are targeted, and (2) change the display name for each device instead of the Collector id. 

    Thanks,

    Sarah

  • Hi Sarah,

    Thanks a lot for sharing it.

    I suppose I have made it work.

    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.StringEntity;
    import org.apache.http.entity.ContentType;
    
    
    //define credentials and url
    def accessId = 'xxx';
    def accessKey = 'xxx';
    def account = 'xxx';
    
    // Change GroupID
    // Please note: It does not work on the group's child groups.
    // Only works on devices in the parent group.
    
    def GroupID = 'xxx'
    
    def resourcePath = "/device/groups/" + GroupID+ "/devices"
    def queryParams =''
    def url = "https://" + account + ".logicmonitor.com" + "/santaba/rest" + resourcePath + queryParams
    def deviceID = []
    
    //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());
    
    JsonSlurper slurper = new JsonSlurper()
    def json = slurper.parseText(responseBody)
    def items = json.data.items
    
    // Iterate all of devices in the parent group
    // Please note: It does not work on the group's child groups.
    
    for (i=0; i<items.size(); i++){
        deviceID.add(items[i].id)
        // You can customize following line whatever you like. At this example, I made Displayname to Displayname + "@logicmontior.com":
        items[i].displayName = items[i].displayName + "@logicmonitor.com";
        items[i] = JsonOutput.toJson(items[i])
        StringEntity params = new StringEntity(items[i],ContentType.APPLICATION_JSON);
    
        epoch = System.currentTimeMillis(); //get current time
        resourcePath =  "/device/devices/" + deviceID[i]
        requestVars = "PUT" + epoch +  items[i] + 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
        url = "https://" + account + ".logicmonitor.com" + "/santaba/rest" + resourcePath;
        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();
  • I'm working on a similar project (system names came in as IP addresses as we didn't have all of our reverse lookups populated in DNS.  I'm a powershell person, so I have to construct my JSON manually.  While I was working on my Failover Cluster Grouping script, I used this JSON structure for a PUT procedure to create a new custom property:

    {
      "type"  : "custom",
      "name"  : "Failover.Cluster.GUID",
      "value" : "$ClusterID"
    }

    What type should be used to access the system properties?

    Would the method be PUT or PATCH? I can try them both, but it would save a couple of minutes (and I'm lazy).

    Specifically, I need to alter name, system.displayname, and system.hostname (I'm filling with the value of ##system.sysname## which came in correctly during the initial discovery.

  • OK...

    Doing a get on the device got me a list of systemproperties that had the type listed in the returned JSON object.

    With that information, this works for the name and the hostname, but not the displayname:

    # Change Properties
    # Construct URL
    $resourcePath   = "/device/devices/2332"
    $url            = $URLRoot + $resourcePath
    
    # Construct Data Body
    $data = `
    @"
    {
        `"name`" : `"Server Name`",
        `"systemProperties`" : [
            {
                `"type`"  : `"system`"             ,
                `"name`"  : `"system.displayname`" ,
                `"value`" : `"Server Name`"
            }, {
                `"type`"  : `"system`"             ,
                `"name`"  : `"system.hostname`"    ,
                `"value`" : `"Server Name`"
            }
        ]
    }
    "@
    
    write-output "Making Request: `n $data"
    
    $response       = Send-Request   `
        -accesskey    $accessKey     `
        -accessid     $accessId      `
        -URL          $url           `
        -data         $data          `
        -httpVerb     "PATCH"
    
    write-output "response: `n $response"

    Why is system.displayname different than all of the other properties?

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

    @Cole McDonald can you clarify your question / what you're trying to do? In general, system properties cannot be directly modified. You can change system.displayname by editing the displayName for the device (via API or UI) & system.displayname will update automatically.

  • Everything I need to do is at scale, so it's all got to be accessible programmatically.  Some systems pulled in with incorrect information, so I'm trying to correct them. (it's correct information, but not the info we need in that location for the way we use monitoring).  Our SQL clusters, due to the fact that we're a multi-tenant MSP, have several IP addresses, all associated with their own DNS entry.  Since they all came from the same source, most of them didn't map to the correct DNS name correctly due to how LM is grabbing its initial info during discovery.  So I've got to A) remap the existing, incorrect devices and B) Prepare for any future devices being added that may encounter the same problem.  Since adding a new tenant will add between a dozen and hundreds of servers, I'd rather not have to sift through them manually in the future, so fully automated is my preferred option.

    Is there a specific reason that the displayname is inaccessible to the RESTAPI?  I assume I'm accessing it correctly as the other fields are changing correctly.

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

    @Cole McDonald got it - you can change displayname via REST API, but you have to edit the 'displayName' attribute of the device, not the 'system.displayname' property for the device. The system property should update to reflect whats in the displayName field for the device (which can be populated both via UI or REST API).

  • Thank you Sarah.  Are these differences between the interface naming conventions and the scripted application of attributes documented somewhere I can reference in the future?

  • As part of a workaround, I changed our alerts to reference the sysname which does at least show us where we need to log in.  Our naming conventions allow us to triage more quickly by telling us whether it's production or dev, so we know if we need to address it on the weekend at 3am rather than waiting for Monday to look into the alert.  Getting this part wrong would increase our person hours... so I needed a quick solution.  One of my favorite comedians is Steven Wright.  In one of his standup shows, he has a moment where he's taking a drink of water.  The glass is on a stool in the middle of the stage.  When he tries to set the glass back on the stool, he has difficulties doing so because he's trying to set it right on the edge of the stool and it keeps trying to tip off.  After a few attempts, he moves the stool.  This is how I approach problem solving :)/emoticons/smile@2x.png 2x" title=":)" width="20">  If the piece you need to fix won't cooperate, change the environment to meet that need.