November 4, 2024
Unlocking the Power of UIMAPI: Automating Probe Configuration
Written by: Steve D'Arcy
Key Takeaways
|
|
The UIMAPI is a RESTful API. With UIMAPI you can programmatically perform almost any action in your DX UIM environment. Using the Swagger front-end as a guide, you can manually execute REST endpoints. However, many customers would rather use a program to automate these actions.
This blog focuses on automating probe configuration. We outline how to use a Java program to interact with the API, offering examples. However, you can employ any programming language that offers support for a RESTful interface. Essentially, a RESTful endpoint is a URL that supports several actions: GET, POST, PUT, and DELETE. For UIMAPI, you will also need credentials. You can perform most GET actions using a web browser and navigating to the URL. As shown in the image below, the Swagger documentation for UIMAPI describes each type of endpoint.
This blog covers the viewing and updating of the net_connect probe as well as creating a new profile, all via the UIMAPI RESTful interface. See my prior post to learn more about using UIMAPI to streamline maintenance modes.
This blog is focused on using the raw configuration file rather than the Monitoring Configuration Service (MCS). If you are interested in using the UIMAPI to manage MCS profiles, look out for my future blogs.
Note: All probe configuration actions are directed at the device and probe, wherever it is running. In this example, the net_connect probe is running on the primary hub. All examples use the base URL to my localhost/UIMAPI endpoints, but they will also work with a remote hostname/IP address as well:
All examples are using JSON but the UIMAPI also supports XML. |
Authenticating the UIMAPI
All UIMAPI endpoints must have authentication, which features a DX UIM user with Web Service ACL permissions, Base64 encoded as a single string {user}:{password}. You can do this once at the start of your program and the encoded string can be sent to every endpoint call. The bytesEncoded string is passed to each endpoint call made.
Here’s an example of Java code:
// Encode the credentials – define user & pwd variables with your credentials
bytesEncoded = Base64.getEncoder().encodeToString((user+":"+pwd).getBytes());
Using HTTP and HTTPS protocols
If using the HTTPS protocol, a certificate may be required. The DX UIM documentation details the process of adding a certificate to a keystore. To establish a secure connection, every endpoint call in these examples requires the keystore and the keystore password.
If you are using the HTTP protocol, set the keystore and keystore password values to null.
Getting a single configuration key value
To get a single configuration key value, use the /probes/config end point:
{base_url}/probes/config
The payload defines the value you want to GET. This requires the address of the probe and the configuration key. The domain, hub, robot, and probe point to where the net_connect probe is running and the key value is the key you want to GET.
The payload is:
{
"domain":"Validation",
"hub":"Office",
"robot":"primary",
"probe":"net_connect",
"key":"/profiles/centos1/active"
}
Using the URL (updated with your environment) plus the payload, GET the configuration key value (payload) along with the encoded credentials (bytesEncoded).
Here’s the Java code example:
// Get a config key value from a profile
payload = "{\"domain\":\"Validation\",\"hub\":\"Office\",\"key\":\"/profiles/centos1/active\",\"probe\":\"net_connect\",\"robot\":\"primary\"}";
responseBody = RestCalls.runRestPost(baseUrl, "/probes/config/", payload, bytesEncoded, keystore, keypwd);
System.out.println("Active: " + responseBody);
This will output the value of the /profiles/centos1/active key:
Active: "yes"
You can view the Active value in Admin Console or Infrastructure Manager:
Getting the entire configuration file
To GET the entire configuration file, the probes GET endpoint requires environment values in the URL string itself:
{base_url}/probes/{domin}/{hub}/{robot}/{probe}/config
These values point to the primary hub where the net_connect probe is running. In this example, the URL will be:
{base_url}/probes/Validation/Office/primary/net_connect/config
Using the URL (updated with your environment), GET the configuration file using the encoded credentials (bytesEncoded). No payload is required.
This is the Java code example:
//Get the entire config file
responseBody = RestCalls.runRestGet(baseUrl, "/probes/Validation/Office/primary/net_connect/config", "", bytesEncoded, keystore, keypwd);
System.out.println(responseBody);
This will output a JSON array of key/value pairs in your net_connect configuration file:
{
"probeConfigKey" : [ {
"key" : "/profiles/centos1/ping",
"value" : "yes" }, {
}, {
"key" : "/profiles/centos1/timeout",
"value" : "2"
}, {
…
}, {
"key" : "/messages/ping threshold failed/token",
"value" : "threshold_fail"
} ]
}
Note: This output is truncated. The actual output was 765 lines, but this portion gives you an idea what to expect. |
You can view the values in Admin Console or Infrastructure Manager:
Updating a profile
In this example, we are going to update a configuration key value. The process is the same regardless of the key, so the key we are going to update is a profile active key, which was used in the above example. We’re changing its value from yes (active) to no (inactive). This will disable the profile.
Updating a single configuration key value uses the POST endpoint and requires environment values in the URL string:
{base_url}/probes/{domin}/{hub}/{robot}/{probe}/config
These values point to where the net_connect probe is running. In this example, use
{base_url}/probes/Validation/Office/primary/net_connect/config
The payload is:
{
"encrypt":"false",
"key":"/profiles/centos1/active",
"value":"no"
}
Using the URL (updated with your environment) plus the payload, POST the configuration key value (payload) along with the encoded credentials (bytesEncoded).
Here’s the Java code example:
// Update a config key - this can also add a key if not there
payload = "{\"encrypt\":\"false\",\"key\":\"/profiles/centos1/active\",\"value\":\"no\"}";
responseBody = RestCalls.runRestPost(baseUrl, "/probes/Validation/Office/primary/net_connect/config", payload, bytesEncoded, keystore, keypwd);
// Get a config key value from a profile
payload = "{\"domain\":\"Validation\",\"hub\":\"Office\",\"key\":\"/profiles/centos1/active\",\"probe\":\"net_connect\",\"robot\":\"primary\"}";
responseBody = RestCalls.runRestPost(baseUrl, "/probes/config/", payload, bytesEncoded, keystore, keypwd);
System.out.println("Profile: centos1 - Active: " + responseBody);
This will output the value of the /profiles/centos1/active key:
Active: "no"
You can view the Active value in Admin Console or Infrastructure Manager:
Creating a new profile
In this example, we create an entirely new profile using a REST call. The profile added will be named centos4 and have a one-minute interval while monitoring the UIM Robot Service.
Adding a new profile is done using the PUT endpoint, which requires environment values in the URL string:
{base_url}/probes/{domin}/{hub}/{robot}/{probe}/config
These values point to the primary hub where the net_connect probe is running. In this example, the URL will be:
{base_url}/probes/Validation/Office/primary/net_connect/config
The payload is:
payload = "["
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/active\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/QoS\",\"value\":\"yes\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/ping\",\"value\":\"yes\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/interval\",\"value\":\"1min\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/hostname\",\"value\":\"centos4\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/ip\",\"value\":\"172.16.217.140\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/timeout\",\"value\":\"2\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/failures\",\"value\":\"1\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/retries\",\"value\":\"3\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/dynamic_ip_monitoring\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/msg_ok\",\"value\":\"MsgConnectOk\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/msg_fail\",\"value\":\"MsgConnectFail\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/qos_source\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/source\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/target\",\"value\":\"2\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/icmp_size\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/flags\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/IPLongValue\",\"value\":\"184341980\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/alarm\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/threshold_ok\",\"value\":\"ping threshold OK\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/threshold_fail\",\"value\":\"ping threshold failed\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/icmp_threshold\",\"value\":\"100\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/alarm_on_packet_loss\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/packets_to_send\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/max_packets_lost\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/qos_on_packets_lost\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/delay_between_packet_to_send\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/max_jitter\",\"value\":\"2000\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/alarm_on_jitter\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/active\",\"value\":\"yes\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/alarm\",\"value\":\"yes\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/QoS\",\"value\":\"yes\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/wait_to_send_command\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/timeout\",\"value\":\"10\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/retries\",\"value\":\"3\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/delay_between_retries\",\"value\":\"0\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/challengeresponsetimeout\",\"value\":\"1000\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/sendcommand\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/responsemustcontain\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/sendcommand2\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/response2mustcontain\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/sendcommand3\",\"value\":\"no\"},"
+ "{\"encrypt\":\"false\",\"key\":\"/profiles/centos4/services/NimBUS_Robot/response3mustcontain\",\"value\":\"no\"}"
+ "]";
Note: The payload is an array in which each key is represented as a separate JSON object. Each object is followed by a comma, except for the last one. The entire JSON array must be enclosed in square brackets [ ], even if it contains only one object. |
This is the Java code example:
// Create a new profile
int rc = RestCalls.runRestPut(baseUrl, "/probes/Validation/Office/primary/net_connect/config", payload, bytesEncoded, keystore, keypwd);
System.out.println("Return Code: " + rc);
This will output the following Return Code:
Return Code: 204
You can view the new centos4 profile in Admin Console or Infrastructure Manager:
Appendix A
Here are all the REST methods used in the examples. These methods are in a class named RestCalls.
runRestPost method
public static String runRestPost(String baseUri, String path, String payload, String credentials, String keystore, String keypwd) throws ClientProtocolException, IOException {
String responseBody = null;
CloseableHttpClient client = setupHttpClient(baseUri, keystore, keypwd);
logger.log(NimLog.DEBUG, "URL: "+ baseUri+path);
HttpPost request = new HttpPost(baseUri+path);
request.addHeader(HttpHeaders.AUTHORIZATION,"Basic " + credentials);
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setEntity(new StringEntity(payload, StandardCharsets.UTF_8));
HttpResponse response = client.execute(request);
int rc = response.getStatusLine().getStatusCode();
//System.out.println("RC: " + rc + " : response: " +response);
if (response.getEntity() != null) {
responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
}
if (rc >= 200 && rc < 300) {
// do some error checking here
return responseBody;
} else {
logger.log(NimLog.ERROR, "Got response code "+rc+" from method: "+response.getStatusLine().getReasonPhrase());
}
return null;
}
runRestGet method
public static String runRestGet(String baseUri, String path, String payload, String credentials, String keystore, String keypwd) throws ClientProtocolException, IOException {
String responseBody = null;
CloseableHttpClient client = setupHttpClient(baseUri, keystore, keypwd);
HttpGet request = new HttpGet(baseUri+path+payload);
request.addHeader(HttpHeaders.AUTHORIZATION,"Basic " + credentials);
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
HttpResponse response = client.execute(request);
int rc = response.getStatusLine().getStatusCode();
responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
//System.out.println("Response body: " + responseBody);
if (rc >= 200 && rc < 300) {
return responseBody;
} else {
logger.log(NimLog.ERROR, "Got response code "+rc+" from method: "+response.getStatusLine().getReasonPhrase());
}
return responseBody;
}
runRestPut method
public static int runRestPut(String baseUri, String path, String payload, String credentials, String keystore, String keypwd) throws ClientProtocolException, IOException
{
CloseableHttpClient client = setupHttpClient(baseUri, keystore, keypwd);
logger.log(NimLog.DEBUG, "URL: "+ baseUri+path);
HttpPut request = new HttpPut(baseUri+path);
request.addHeader(HttpHeaders.AUTHORIZATION,"Basic " + credentials);
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setEntity(new StringEntity(payload, StandardCharsets.UTF_8));
HttpResponse response = client.execute(request);
int rc = response.getStatusLine().getStatusCode();
if (rc >= 200 && rc < 300) {
// do some error checking here
return rc;
} else {
logger.log(NimLog.ERROR, "Got response code "+rc+" from method: "+response.getStatusLine().getReasonPhrase());
}
return rc;
}
setupHttpClient method
private static CloseableHttpClient setupHttpClient(String baseUri, String keyfile, String keypwd) {
CloseableHttpClient httpclient = null;
try {
if (baseUri.startsWith("https")) {
logger.log(NimLog.DEBUG, "setupHttpClient: Setting up https client");
//Creating SSLContextBuilder object
SSLContextBuilder SSLBuilder = SSLContexts.custom();
// Loading the Keystore file
File file = new File(keyfile);
// Update the password for your key file
SSLBuilder = SSLBuilder.loadTrustMaterial(file,"#####".toCharArray());
// Building the SSLContext
SSLContext sslcontext = SSLBuilder.build();
// Creating SSLConnectionSocketFactory object
SSLConnectionSocketFactory sslConSocFactory = new SSLConnectionSocketFactory(sslcontext, new NoopHostnameVerifier());
// Creating HttpClientBuilder
HttpClientBuilder clientbuilder = HttpClients.custom();
// Setting the SSLConnectionSocketFactory
clientbuilder = clientbuilder.setSSLSocketFactory(sslConSocFactory);
// Building the CloseableHttpClient
httpclient = clientbuilder.build();
return httpclient;
} else {
logger.log(NimLog.DEBUG, "setupHttpClient: Setting up http client");
httpclient = HttpClients.custom()
.setConnectionTimeToLive(20, TimeUnit.SECONDS)
.setMaxConnTotal(400).setMaxConnPerRoute(400)
.setDefaultRequestConfig(RequestConfig.custom()
.setSocketTimeout(120000).setConnectTimeout(5000).build())
.setRetryHandler(new DefaultHttpRequestRetryHandler(5, true))
.build();
return httpclient;
}
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) {
logger.log(NimLog.ERROR, "setupHttpClient: Exception trying to create the http client: " + e.getLocalizedMessage());
logger.logStackTrace(NimLog.ERROR, e);
}
return httpclient;
}
Steve D'Arcy
Steve D’Arcy is one of Broadcom’s trusted advisors, learning about the challenges customers face and helping overcome them to ensure customers’ business goals are met. He has worked with unified infrastructure management since 2010, and during this time has collaborated closely with engineering and field operations to...
Other posts you might be interested in
Explore the Catalog
Blog
September 16, 2024
Streamline Your Maintenance Modes: Automate DX UIM with UIMAPI
Read More
Blog
September 6, 2024
CrowdStrike: Are Regulations Failing to Ensure Continuity of Essential Services?
Read More
Blog
August 28, 2024
Monitoring the Monitor: Achieving High Availability in DX Unified Infrastructure Management
Read More
Blog
August 23, 2024
Elevate Your Database Performance: The Power of Custom Query Monitoring With DX UIM
Read More
Blog
August 16, 2024
Enhancing IT Monitoring with DX UIM 23.4 Cumulative Update 2
Read More
Blog
July 26, 2024
Objective Monitors in the Context of Active Directory (AD) Servers
Read More
Blog
May 3, 2024
Infrastructure Observability Can Help Navigate Cloud Repatriation
Read More
Blog
April 16, 2024
DX UIM 23.4: Improved Zero-Touch Monitoring, Updated MCS Architecture
Read More
Blog
January 11, 2024