Coding Essentials III – NetDevOps Series, Part 5

Previous posts in the NetDevOps Series are available here.

Let’s finalize our review of the different foundational coding building blocks that network engineers need to understand and use when entering the programmability world.

REST APIs

In previous posts you have seen it several times already, so by now you might be wondering what is REST? It stands for Representational State Transfer, and it was born from the need to create a scalable Internet, where software systems could interact with each other, in an uniform and efficient approach.

It is a simple-to-use communications architecture style (not a standard) for networked applications, based on the client-server model. It expects all information required for the transaction to be provided at the time of the request. Client could be an application or a REST client, like Postman for development and testing. Server could be a system, network device, or network management application.

REST is stateless, so the server will close the connection after the specified exchange is completed, and no state will be maintained on the server side. This way it makes transactions very efficient.

The same as you use a HTTP get method when browsing the internet and the server provides you with a website in HTML format that your browser decodes to make it human readable, REST APIs answer to get requests from other systems with structured data (in JSON or XML) specifically addressed to them.

Think about SDN and NFV, where different types of controllers need to communicate and exchange information with multiple devices. Applications sitting on top of those controllers can actually query anything that the controller knows about the network below it. This can be operational data, configuration data stats about a single device with a 10GE interface, etc. Applications then take this information, process it and then program the controller by sending a post instead of a get request.

RESTful APIs are REST-based APIs, based on response-request communications using the HTTP protocol for the following operations (CRUD):

Post: Create a new resource

Get: Retrieve/Read a resource

Put: Update an existing resource

Delete: Delete a resource

It includes five components that may be required in each Request:

URL: application server and the API resource

Auth: there are few different authentication methods, not standardized, required to identify who is making the request (HTTP Basic, Custom, OAuth, none)

Headers: define content-type and accept-type, communicating to the server the format of data we will send and expect to receive (JSON or XML)

Request Body (optional): may be missing if no data is required to be sent with the request

Method: What is the task we ask the server to perform (ie. use POST to create a new record, or PUT to update an existing one)

Let’s take a look at the format in this example:

url = DNAC_IP + '/api/v1/host?hostIp=' + client_ip
header = {'content-type': 'application/json', 'Cookie': dnac_jwt_token}
response = requests.get(url, headers=header, verify=False)
client_json = response.json()
client_info = client_json['response'][0]

First we need to define the URL with the IP address of the end system (ie. DNAC_IP) and the route to the required resource (ie. /api/v1/host?hostIp= combined with the IP of an end system). Then we specify the required headers, defining what is the format we are sending (JSON) and the required auth cookie. With that info we open the connection, make the request and store the response to parse it.
As long as these are HTTP requests we are sending, server will answer with a HTTP status code, headers and a response body.

Some possible HTTP status codes:

2xx Success: 200 OK, 201 Created

4xx Client Error: 400 Bad Request, 401 Unauthorized (something is wrong the authentication), 404 Not Found (most likely URL is wrong, or payload is wrongly formatted)

5xx Server Error: 500 Internal Server Error

Headers will define the content-type (JSON or XML), cache control, date and encoding.

The response body will be the payload, including the requested data in JSON or XML, depending on the headers provided during the request.

Response 200 / success
Cache-Control →no-cache
Content-Type →application/json;charset=UTF-8
…
{
"hostIp" : "10.93.140.35" ,
"hostMac" : "00:0c:29:6d:df:40" ,
"hostType" : "wired" ,
"connectedNetworkDeviceId" : "601c9ead-576c-402d-bcb1-224235b1e020" ,
"connectedNetworkDeviceIpAddress" : "10.93.140.50" ,
"connectedInterfaceId" : "eb613db0-0994-44ec-9146-1b65346f3d07" ,
"connectedInterfaceName" : "GigabitEthernet1/0/13" ,
"connectedNetworkDeviceName" : "NYC-9300" ,
"vlanId" : "123" ,
"lastUpdated" : "1528324633014" ,
"accessVLANId" : "123" ,
"id" : "841f9433-0d2c-4735-afe8-beb7547b7883"
}

API Documentation

Documentation is always essential, but in this case even more, because REST APIs are an architectural style, not a standard. So, docs will define specifically what you need to send to your network device, and what you should expect in return.

Quality of the API documentation is the most important factor in API adoption, because it determines how difficult is to work with your APIs. You might have the most powerful APIs, but if they are not documented correctly nobody will be able to leverage them.

APIs are very often documented in the platform itself, offering you the option to test them directly there without needing to write any code, or even know a programming language.

It is also common for them to offer you the option to automatically generate sample code in different programming languages, so you can directly use it in your developments.

Python

When talking about programmability and APIs you need to pick your favorite programming language to let your system know what you want it to do, and how it needs to communicate with your network devices APIs. The goal will be to automate and script actions using the APIs provided by network devices, controllers, and applications. There is a myriad of different options when choosing your programming language (Python, Ruby, Go, JavaScript, C#, etc) and each developer will have his/her own preferences.

One very good option for network engineers to get started with programming is Python. It is one of the most popular programming languages across the globe for several reasons:

Lots of available resources

Extensive libraries

Most SDKs developed in Python

Powerful and fast

Ubiquitous

Easy to learn and friendly

Open

Wide support on different devices and platforms

Rich and active support communities

Most wanted language in 2017 & 2018

Summary

APIs and programming languages have evolved and matured to the point of being useful and applicable to the domains of infrastructure engineers.

The net-effect being that you can get powerful things done with relatively small amounts of code. And by so doing, you can automate the repetitious and/or labor-intensive parts of your job freeing you up to focus your time and effort on tasks deserving of your intellect.

Network programmability provides consistent and dynamic infrastructure configuration by automating deployments and simplifying network management, bringing the following main benefits:

Automation

Time and cost optimization

Reduced errors

Integration

Innovation

In my next post we will look at how we can apply DevOps principles to network configuration management, and the kind of benefits we can obtain from that approach. See you next week, stay tuned!

Any questions or comments please let me know in the comments section below, Twitter or LinkedIn.

Join DevNet to access the learning labs, docs, and sandboxes you need for network automation. And check out this expert-led, video course for learning network programmability basics.