SNMP module in Python
SNMP, short for Simple Network Management Protocol, is a necessary tool for SDN and is the best option to control devices in software. Even apart from this, in-application access is the primary purpose of SNMP. Without a doubt, all monitoring systems utilize SNMP in order to monitor and control servers and network devices. Having this massive strength that comes from SNMP in a script would be amazing. Hence, we will discuss the utilization of SNMP in the Python programming language in this tutorial.
But before we get started, let us discuss the SNMP.
Understanding the SNMP
SNMP, also known as Simple Network Management Protocol, is a standard way to communicate between a management server and a remote device, the agent. The goal of SNMP is to have the manager understand (or even change) data on the agent. For Instance, the manager can check which interfaces are up and which are down or change the hostname of the remote device.
Our script enables a Python program on a management station for controlling a remote device executing an SNMP agent.
The SNMP agent prepares most of the details the manager can read or change in a special table, the MIB. The MIB is a tree-like structure, where a number will denote each node in the tree. For Instance, 184.108.40.206.2.1.1 denotes the description of the system. If some of us wonder where this chain of numbers came from, this is the whole tree structure! Each number associates with a name. Consequently, we can translate that into a more explicative iso.org.dod.internet.mgmt.mib-2.system.sysDescr.
Now, let us discuss the use of SNMP in the Python programming language with the help of the Python PySNMP module.
Understanding the PySNMP module
PySNMP is an open-source module for Python. Unlike telnet or HTTP, Python does not natively implement SNMP. After all, just network and system engineers will require a Python developer on the plant. PySNMP does a great job of covering the lack of native Python. In general, the PySNMP module allows us to utilize any version of SNMP, both as an agent or as a manager. Creating an agent implies that we are building an application or an appliance. However, we will only be discussing the use of PySNMP in managing a remote device.
Moreover, we will understand the different functionalities of PySNMP in Python. The main target for this tutorial will be to create a quick python program that can make things easy for us. Within the program, we will have all the operations of SNMP we require.
So, let's get begun.
Preparing the environment
First of all, we have to install the PySNMP module. We can use the pip installer in order to install the required module with the help of the following command.
The module will be installed in the system as the version of Python and pip.
Verifying the Installation
In order to check whether the module has been installed in the system properly or not, we can try importing the module and execute the program.
Once the installation is complete, create a new Python file and type the following syntax in it.
Now, save the file and run the file using the following command in the command prompt.
If the program runs without raising any import error, the module is installed properly. Else it is recommended to reinstall the module and refer to its official documentation.
Understanding the Python SNMP Get operation
The Get operation of SNMP enables us to retrieve the value of an individual object in the MIB. We can also utilize it for getting a list of individual objects. We can begin writing out the get() function as shown below:
From the above snippet of code, we can observe the leveraging of the High-Level API of PySNMP. We have defined a simple function as get(), which first requires a target (IP or remote device name). Then, it needs the list of Object IDs (oids) we need to get and, after that, a set of credentials for the session authentication. We can also specify a distinct UDP port if we need, and utilize a prevailing SNMP engine or custom context. We may require utilizing the same engine for all the operations on the same device, which saves resources. However, this is not required for a simple snippet of code so that we can ignore both engines as well as context.
The function generates a handler for the session of SNMP and fetches the details from it. In order to perform that, it depends on two methods we have to create: construct_object_types and fetch.
Constructing Object Types
As we discussed earlier, having more strength implies more complexity. Thus, the hlapi.getCmd() function requires some special hlapi.ObjectType objects, and not a simple list of string OIDs. Hence, the construct_object_type function creates as per the needs of PySNMP. We can simply copy and paste it into the code if we do not have time. However, this should be a very simple function; let us take a look:
The above snippet of code returns a list that can be expanded by prepending a *, as we did in the get() method.
The fetch() function is a masterpiece of the Python SMP Tutorial. In general, we wrote it so that we can reutilize it for other functions based on PySNMP, such as get-bulk. It simply loops on the handler multiple times as per the count variable. If there is any error raised, the process will be stopped, and the RuntimeError message will be returned. In any other scenario, it stores the data in a list of dictionaries.
In the above snippet of code, we have constructed the try-except method to stop iteration for a specific reason. In cases where the user specifies the count higher than the number of objects we actually have, we simply stop and return what we got so far. This is the purpose of the construct.
What is the need of returning a list of dictionaries? In every get operation, we can get various object IDs. Hence, every dictionary will consist of the object ID as the key and the value of the OID in the MIB as the value of that key. In a scenario where we need more than one OIDs in a single get, we will return a dictionary with multiple keys. But what is the need for a list, then? Using the get operation, we can retrieve the data only once. However, as we will see in get bulk, we might need to get similar details multiple times on various instances. Let us consider an example for better understanding. Suppose we need to check the errors on all the interfaces: the information is always the errors; however, we have different instances (one per interface). We can visualize it using a list, where each data element is a dictionary depicting an instance.
Note: The fetch() function depends on another function we must create: cast(). This function translates the received data from PySNMP to int, float or string.
Let us consider the following snippet of code for the same:
In the above snippet of code, we have defined a function where we used the try-except method to check for any raised error.
The authentication system of the PySNMP library is strong and quite straightforward. There is no reason to write an extra layer above it, so we can directly utilize it. The get() function, along with the rest, have a special authentication object in the credentials variable. This object is varied if we use SNMPv2c or SNMPv3.
In the case of SNMPv2c (or lower), we have to specify the community. We can do that using the CommunityData object, as shown below:
Instead, SNMPv3 is complex. This is because it utilizes a user with two passwords and two protocols: The first for authentication and the other for encryption. Hence, we have to specify the name of the user, authentication password, authentication protocol, the password for encryption, and protocol for encryption. We can do it using the UsmUserData class.
Let us consider the following example for better understanding.
In the above snippet of code, we have used the UsmUserData class and entered the required details. It is simpler than it appears; we have to know the remote device's protocols. However, some of us may refer to the complete official documentation on UsmUserData.
Getting the hostname
Now, let us test the get() function. We will use it to retrieve the hostname of the device, which is object 220.127.116.11.18.104.22.168.0. We can simply write the following snippet of code:
In the above snippet of code, we have printed the result of the get() function in getting the hostname of the device.
Note: Here, we are not getting a list of dictionaries, but just a dictionary. This is deliberate, and the get() function will act like that at all times. Generally, we know that the function executes only once; it can't create multiple instances. Thus, we return the first element we got from fetch().
Understanding the Python SNMP Get Bulk
The get_bulk() method retrieves more than one instance of the same Object ID, let's say one for every interface. This function becomes supportable when we are working with tables, such as the routing table of interface one. It is quite straightforward and functions similar to the get() method. But it requires some extra details: which object to start with and a number of instances we need to get. We deliver them in start_from and count.
Let us consider the following snippet of code to understand the working of the get_bulk() function.
In the above snippet of code, we have defined the get_bulk() function where we specified the handler. At last, we have returned the fetch() function. As a result, we are expecting a list of dictionaries, so we do not have to extract just the first dictionary as we did use the get() function.
Understanding the Python SNMP Get Bulk Auto
The get_bulk_auto() function is the improved version of the get_bulk() function. Suppose we wanted to loop through the device interfaces using get_bulk(). How can we know the number of interfaces? And this becomes necessary as SNMP needs to know how many times to iterate. We cannot know that in advance; however, we can use SNMP as an option to find this information.
We can use the get_bulk_auto() function to tell the code to retrieve the count variable from another OID. Hence, we can specify an object ID instead of specifying a number. The function will make a get for the object and utilize it as a count.
Let us consider the following example for better understanding.
In the above snippet of code, we have defined the get_bulk_auto() function and specified the count variable using get() and return the get_bulk() function.
Using Python SNMP Get Bulk & Get Bulk Auto
Let us consider executing the following snippet of code.
22.214.171.124.126.96.36.199.1.2.1=FastEthernet1/0 188.8.131.52.184.108.40.206.220.127.116.11= 18.104.22.168.22.214.171.124.1.2.2=FastEthernet0/0 126.96.36.199.188.8.131.52.184.108.40.206= 220.127.116.11.18.104.22.168.1.2.3=FastEthernet0/1 22.214.171.124.126.96.36.199.188.8.131.52=Test Desc 184.108.40.206.220.127.116.11.1.2.4=Serial2/0 18.104.22.168.22.214.171.124.126.96.36.199= 188.8.131.52.184.108.40.206.1.2.5=Serial2/1 220.127.116.11.18.104.22.168.22.214.171.124= 126.96.36.199.188.8.131.52.1.2.6=Serial2/2 184.108.40.206.220.127.116.11.18.104.22.168= 22.214.171.124.126.96.36.199.1.2.7=Serial2/3 188.8.131.52.184.108.40.206.220.127.116.11= 18.104.22.168.22.214.171.124.1.2.9=Null0 126.96.36.199.188.8.131.52.184.108.40.206=