REST API and talking to 1000 Netrounds Test Agents - Automation makes you Feel Awesome!
Part 1
I had the pleasure of writing about the Netrounds solutions before, and I would like to talk about this awesome technology a bit more. If you haven’t had a chance to see the part-1, I strongly suggest you stop reading below and click on this now :)
Netrounds Control Center(NCC) supports REST API. REST API basically allows end users to interact with the application without using the NCC GUI. Instead of doing click and configure a test template or click on each Test Agent on the NCC and confirm their status, you can automate this manual work with the REST API.
You might think that writing the code to automate this action does not sound easier than clicking on a button to see the result. However, automation works the best for an environment;
1 — where the relevant information needs to be pulled from (or pushed to)many nodes/instances.
2 — or the action is repetitive

To make this more clear let’s create a simple task;
Requirement: I have 1000 Test Agents which I would like to check whether they are online or offline for every 10 seconds.
Manually doing this would require clicking on 100 Test Agents non stop for every ten seconds :) and plus writing the output down for each click. Not sure how would you do that but I would be super tired of trying it.
Solution Overview: A Simple Python Script that pulls the Test Agent information from Netrounds Control Center. Saves the output to a json file. And it goes through the json file and checks each available Test Agent name and status. Second step is to extract the Test Agent names and statuses to save them to a csv file. This csv file can be used for any other purposes. Maybe to visualise the data via a third party library or import it to an another tool like Tableau.
I imagine the end result csv similar to this:

Solution Deep Dive:
You can use pretty much any programming language to accomplish this task. My preference here is to use Python 3.
Before we dive into code, let me show you how easily you can start using REST API on the Netrounds Control Center.
Step 1- Figure out the available end points, Accessing the REST API browser:
You can access to the API browser for the REST API at https://NCC_Address/rest/
The API browser is interactive and enables you to try out the REST API operations manually. It also provides documentation of the REST API features. Furthermore, immediately below the heading, it links to a JSON schema which exhaustively describes the REST API

I scroll down on Swagger UI and realise that there is a relevant end point for the TEST Agents.
It is a GET request for /accounts/{account}/test_agents/

Description says that by using this end point I can see the “online” attribute which is basically a boolean value. For an offline TA this attribute would return False.
By seeing this information, I can imagine that I will pull the information on /accounts/{account}/test_agents/ for all Test Agents, save it to a .json file locally and I will go through the .json file to extract “name”, “online” and put those two together with a timestamp to a csv file.

Step 2 - Writing our precious script!
import requests
import json
import csv
import time
import datetime
url_system_status = "https://eser.test.netrounds.com/rest/accounts/eser/test_agents/"
headers = {"API-Token": "somethinghere"}
agent_list = []
def pull_info():
response = requests.get(url_system_status, headers=headers).json()
with open('agents_eser.json', 'w') as config_file:
json.dump(response, config_file, indent=4)
with open('agents_eser.json', 'r') as config_file:
data = json.load(config_file)
agents = data['items']
for agents in agents:
agent_states= (agents['name'],agents['online'], datetime.datetime.utcnow())
print (agent_states)
agent_list.append(agent_states)
print(agent_list)
def create_csv_agents():
with open('agents_eser_csv.csv', 'w') as csv_agent:
fieldnames = ['Agent Name','State', 'Timestamp']
file = csv.DictWriter(csv_agent, fieldnames=fieldnames)
file.writeheader()
file = csv.writer(csv_agent, delimiter= ',' ,
quotechar='|', quoting=csv.QUOTE_NONE)
for agent_lists in agent_list:
file.writerow(agent_lists)
if __name__ == '__main__':
while(True):
agent_info = pull_info()
create_csv_agents()
time.sleep(10)What does this script do exactly?
It has two definitions (functions);
def pull_info(): and def create_csv_agents():
def pull_info(): this is where we first do a GET request to the url defined at url_system_status variable. We get the output from the url and save it to a json file (agents_eser)
Here how does the json file look like:
{
"count": 100,
"exclude_default": [
"interface_config",
"ntp_config",
"management_interface",
"interface_names",
"interface_states",
"uptime",
"memory",
"cpu",
"load_avg"
],
"items": [
{
"description": "",
"gps_lat": null,
"gps_long": null,
"id": 5655,
"interface_config_error": null,
"interface_names": [
"eth0",
"eth1"
],
"is_owner": true,
"license": "SW_LARG",
"name": "ta-gc-2",
"online": true,
"tags": [],
"type": "appliance",
"update_error": null,
"updating": false,
"use_public_address": false,
"version": "2.29.1.4"
},
{
"description": "",
"gps_lat": null,
"gps_long": null,
"id": 5656,
"interface_config_error": null,
"interface_names": [
"eth1",
"eth0"
],
"is_owner": true,
"license": "SW_LARG",
"name": "ta-gc-30",
"online": true,
"tags": [],
"type": "appliance",
"update_error": null,
"updating": false,
"use_public_address": false,
"version": "2.29.1.4"
},
{
"description": "",
"gps_lat": null,
"gps_long": null,
"id": 5657,
"interface_config_error": null,
"interface_names": [
"eth1",
"eth0"
],
"is_owner": true,
"license": "SW_LARG",
"name": "ta-gc-33",
"online": true,
"tags": [],
"type": "appliance",
"update_error": null,
"updating": false,
"use_public_address": false,
"version": "2.29.1.4"
},
{
"description": "",
"gps_lat": null,
"gps_long": null,
"id": 5658,
"interface_config_error": null,
"interface_names": [
"eth0",
"eth1"
],
"is_owner": true,
"license": "SW_LARG",
"name": "ta-gc-45",
"online": true,
"tags": [],
"type": "appliance",
"update_error": null,
"updating": false,
"use_public_address": false,
"version": "2.29.1.4"
},
.
.
.
.
.Obviously we have more information than what we are interested in. We need to go through this and get “name”,”online”
This filtering is still done at the def pull_info(): method
with open('agents_eser.json', 'r') as config_file:
data = json.load(config_file)
agents = data['items']
for agents in agents:
agent_states= (agents['name'],agents['online'], datetime.datetime.utcnow())
print (agent_states)
agent_list.append(agent_states)
print(agent_list)Here we ask script to load the ‘items’ part in json file (if we check the json file very carefully we are going to realise that everything we need fall under ‘items’) and from ‘items’ get ‘name’ and ‘online’ + add timestamp of this filtering time and append the end result to a python list names “agent_list”
At this point I have everything I need, to be able to create a csv file. CSV file creation done by the second method: def create_csv_agents():
def create_csv_agents():
with open('agents_eser_csv.csv', 'w') as csv_agent:
fieldnames = ['Agent Name','State', 'Timestamp']
file = csv.DictWriter(csv_agent, fieldnames=fieldnames)
file.writeheader()
file = csv.writer(csv_agent, delimiter= ',' ,
quotechar='|', quoting=csv.QUOTE_NONE)
for agent_lists in agent_list:
file.writerow(agent_lists)This method creates a csv file named agents_eser_csv.csv This csv file is going to have three columns: ‘Agent Name’,’State’, ‘Timestamp’. Each row will be filled by reading the python list “agent_list” which was modified at the previous method.
Below is the part of csv file after the script execution.
Agent Name,State,Timestamp
ta-gc-2,True,2019-07-19 16:31:48.414432
ta-gc-30,True,2019-07-19 16:31:48.414473
ta-gc-33,True,2019-07-19 16:31:48.414482
ta-gc-45,True,2019-07-19 16:31:48.414492
ta-gc-23,True,2019-07-19 16:31:48.414502
ta-gc-43,True,2019-07-19 16:31:48.414514
ta-gc-18,True,2019-07-19 16:31:48.414526
ta-gc-24,True,2019-07-19 16:31:48.414541
ta-gc-22,True,2019-07-19 16:31:48.414557
ta-gc-31,True,2019-07-19 16:31:48.414573
ta-gc-25,True,2019-07-19 16:31:48.414591
ta-gc-48,True,2019-07-19 16:31:48.414608
ta-gc-52,True,2019-07-19 16:31:48.414627
ta-gc-12,True,2019-07-19 16:31:48.414647
ta-gc-44,True,2019-07-19 16:31:48.414813
ta-gc-32,True,2019-07-19 16:31:48.414838
ta-gc-61,True,2019-07-19 16:31:48.414861
ta-gc-16,True,2019-07-19 16:31:48.414885
ta-gc-1,True,2019-07-19 16:31:48.414910
.
.
.
.
.Last part of the script puts these two methods into a loop. State of the agents can be different thus every 10 seconds csv file will be recreated with the up-to-date information.
if __name__ == '__main__':
while(True):
agent_info = pull_info()
create_csv_agents()
time.sleep(10)Step - 3 Feel Awesome!
.=.,
;c =\
__| _/
.'-'-._/-'-._
/.. ____ \
/' _ [<_->] ) \
( / \--\_>/-/'._ )
\-;_/\__;__/ _/ _/
'._}|==o==\{_\/
/ /-._.--\ \_
// / /| \ \ \
/ | | | \; | \ \
/ / | :/ \: \ \_\
/ | /.'| /: | \ \
| | |--| . |--| \_\
/ _/ \ | : | /___--._) \
|_(---'-| >-'-| | '-'
/_/ \_\
