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. |
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());
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.
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:
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:
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:
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:
Here are all the REST methods used in the examples. These methods are in a class named RestCalls.
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;
}
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;
}
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;
}
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;
}