📜 ⬆️ ⬇️

Why a Python Networker? Part two

In the first part, Why the Python webmaster script learned how to collect the hostname of the equipment via SNMP. Unfortunately, for some reason, the second part, to put it mildly, was delayed, but in it I will tell you how to collect and process the rest of the data needed to form the zone files.

We formulate a problem that needs to be solved: it is necessary to generate domain names for routers and their interfaces. The script should from a similar configuration (in this case cisco):
hostname R1.greenhouse
domain service.prov.ru

interface FastEthernet0 / 1.24
description Line to Red House
ip address 10.24.1.1 255.255.255.254
create two records for the forward zone and for the reverse zone:
Fa0 / 1.24.Line_to_Red_House.R1.greenhouse.service.prov.ru. IN A 10.24.1.1
')
1.1.24.10.in-addr.arpa. IN PTR Fa0 / 1.24.Line_to_Red_House.R1.greenhouse.service.prov.ru.

There is bad news: these are the wrong domain names. According to the rules you can use only numbers, letters and “-”. And the hyphen can not stand first and last. To comply with the rules, the entry should look something like this:
Fa0-1-24.Line-to-Red-House.R1.greenhouse.service.prov.ru. IN A 10.24.1.1
With readability there are obvious problems. And if the interface name does not begin with a non-zero digit, and even with a colon? After bringing this to the standard, it becomes quite difficult to understand what and where in these numbers and letters. And I would like to see the traceroute output from the corner of my eye, immediately understand what, where and how, and not engage in the interpretation of output by divination. Therefore, bind was configured with an option that allows you to work with non-standard names. And the script, accordingly, makes the most readable names. Docking the DNS networkers and the global DNS is a bit of a separate conversation, but the easiest way to allocate a separate domain for network equipment, for example, network.megaproduct.org.

To form zone files, we need to collect the hostname values ​​of the routers, the interface names, the description value on these interfaces, and the ip-addresses of these interfaces. The only exception is the record containing the ip-address belonging to the interface Loopback0. This entry will not contain the name of the interface and the value of its description, as this is the domain name of the router.

How to find the right OID?


Let's define OIDs to get the names of the interfaces, ip addresses and description from these interfaces. Our goal is versatility, so we will use the OID of standard MIB files, which are implemented by all vendors. As a rule, the easiest way to find the desired OID is not reading the documentation or googling, but using snmpwalk or any browser MIB that you like best. We are looking at what specific equipment can produce, choose the right one. By running snmpwalk, you will get all the OIDs supported by the device with their values ​​at the time of the poll.

To get started with snmpwalk, you need to install the snmp package and snmp-mibs-downloader:
sudo apt-get install snmp

sudo apt-get install snmp-mibs-downloader
If you want the utilities to work with the named OID in the configuration file /etc/snmp/snmp.conf add the used mib or keyword ALL.
Of course, it is obvious that the use of ALL is not recommended, the number of files is huge, searching all files in a row in many cases is clearly not a good idea. However, in the case of writing a program and searching for the desired MIB file, this is permissible. Do not forget only to leave only the necessary and necessary.
$ cat /etc/snmp/snmp.conf
# As the snmp packages come without MIB files due to license reasons, loading
# of MIBs is disabled by default. If you added the MIBs you can reenable
# loading them by commenting out the following line.
mibs: SNMPv2-MIB: RFC1213-MIB: IF-MIB

#mibs: ALL
zw @ note: ~ $
Check, snmp saw our MIB:
host $ snmptranslate 1.3.6.1.2.1.31.1.1.1.18
IF-MIB :: ifAlias

host $ snmptranslate -On IF-MIB :: ifAlias
.1.3.6.1.2.1.31.1.1.1.18
Make a request for a real box:
host $ snmpget -v 2c -c tilitili 10.239.192.2 1.3.6.1.2.1.31.1.1.1.18.1
IF-MIB :: ifAlias.1 = STRING: Line_to_OUT
The last digit (1) that I added is ifindex. Ifndex is the interface number assigned by the snmp agent to the hardware operating system.

Numbering is done when the agent is initialized (when the OS boots). After each reboot of the equipment, it will be different if you do not instruct the router to memorize the assigned ifindex (google by the keyword ifindex persist).

When working with interfaces, everything is logical, we take an OID, add ifindex, make a request - we get the description of the interface with this Ifindex.

We will request snmpwalk, which will request from the router all available OIDs and their current values:
host $ snmpwalk -v 2c -c tilitili 10.239.192.2

RFC1213-MIB :: ifDescr.1 = STRING: "FastEthernet0 / 0"
RFC1213-MIB :: ifDescr.2 = STRING: "FastEthernet0 / 1"
RFC1213-MIB :: ifDescr.3 = STRING: "Null0"
RFC1213-MIB :: ifDescr.36 = STRING: "Loopback0"
RFC1213-MIB :: ipAdEntAddr.10.239.192.2 = IpAddress: 10.239.192.2
RFC1213-MIB :: ipAdEntAddr.10.239.192.90 = IpAddress: 10.239.192.90
RFC1213-MIB :: ipAdEntAddr.11.0.0.1 = IpAddress: 11.0.0.1
IF-MIB :: ifName.1 = STRING: Fa0 / 0
IF-MIB :: ifName.2 = STRING: Fa0 / 1
IF-MIB :: ifName.3 = STRING: Nu0
IF-MIB :: ifName.36 = STRING: Lo0
IF-MIB :: ifAlias.1 = STRING: Line_to_OUT
IF-MIB :: ifAlias.2 = STRING: Line_to_poligon
IF-MIB :: ifAlias.3 = STRING:
IF-MIB :: ifAlias.36 = STRING:
The snmpwalk output has something to read, it is very verbose, so it’s better to filter it.

You can pay attention, Fastethernet interfaces come with 1 ifindex, and Loopback c 36. A curious detail: ifDesc gives full interface names, ifAlias ​​gives description of interfaces, and ifName gives abbreviated interface names. The use of the full names of the interfaces was dropped immediately, the names due to the contents of the description and so will be long, and the full names of the interfaces will make them even longer.

If we need an OID whose values ​​we know, it is easier to look for them from the snmpwalk output or the MIB browser using search or filtering. If we need an OID, for example, the current value of CPU utilization, then it is easier to search in google or in the documentation :)

Let's look for the necessary OIDs by the values ​​of ip addresses that we know:
host $ snmpwalk -v 2c -c tilitili 10.239.192.2 | grep 10.239.192.2

RFC1213-MIB :: ipAdEntAddr.10.239.192.2 = IpAddress: 10.239.192.2
RFC1213-MIB :: ipAdEntIfIndex.10.239.192.2 = INTEGER: 36
RFC1213-MIB :: ipAdEntNetMask.10.239.192.2 = IpAddress: 255.255.255.255
RFC1213-MIB :: ipAdEntBcastAddr.10.239.192.2 = INTEGER: 1
RFC1213-MIB :: ipAdEntReasmMaxSize.10.239.192.2 = INTEGER: 18024
RFC1213-MIB :: ipRouteDest.10.239.192.2 = IpAddress: 10.239.192.2
RFC1213-MIB :: ipRouteIfIndex.10.239.192.2 = INTEGER: 36
and so on
And from the output it is immediately clear that there is no OID, adding to which ifindex, we would get the interface ip addresses with this ifindex. Note:

RFC1213-MIB :: ipAdEntAddr. + ip address - returns ip address.
RFC1213-MIB :: ipAdEntIfIndex. + ip address - returns ifindex

Thus, we first need to collect ip addresses and ifndex interfaces with these ip addresses, and then collect the names and description of interfaces using ifndex.

Go to the data collection: SNMPGETNEXT and Python


The snmpget method previously used to collect the hostname for solving this problem is completely inappropriate. This method needs an exact OID, but we don’t have one. In such situations, use another method - snmpgetnext. In snmp utilities, the snmpgetnext utility is responsible for this method.

It works like this: SNMPGETNEXT takes an OID and returns the next OID and its value.
host $ snmpgetnext -v 2c -c tilitili 10.239.192.2 1.3.6.1.2.1.4.20.1.1
RFC1213-MIB :: ipAdEntAddr.10.239.192.2 = IpAddress: 10.239.192.2

host $ snmpgetnext -v 2c -c tilitili 10.239.192.2 1.3.6.1.2.1.4.20.1.1.10.239.192.2
RFC1213-MIB :: ipAdEntAddr.10.239.192.90 = IpAddress: 10.239.192.90
And so on. Please note that we do not know the address of the router at the first request, so the first call simply goes to the OID value 1.3.6.1.2.1.4.20.1.1

Let's try to automate these requests. Let's write a function and call it several times:

def snmp_getnextcmd(community, ip, port, OID): # type class 'generator' errorIndication, errorStatus, errorIndex, result[3] #  next     ,      next() return (nextCmd(SnmpEngine(), CommunityData(community), UdpTransportTarget((ip, port)), ContextData(), ObjectType(ObjectIdentity(OID)))) g = (snmp_getnextcmd(community_string, ip_address_host, port_snmp, OID_ipAdEntAddr)) print(g) errorIndication, errorStatus, errorIndex, varBinds = next(g) for name,val in varBinds: print(name.prettyPrint(),' ====== ',val.prettyPrint()) errorIndication, errorStatus, errorIndex, varBinds = next(g) for name,val in varBinds: print(name.prettyPrint(),' ====== ',val.prettyPrint()) errorIndication, errorStatus, errorIndex, varBinds = next(g) for name,val in varBinds: print(name.prettyPrint(),' ====== ',val.prettyPrint()) errorIndication, errorStatus, errorIndex, varBinds = next(g) for name,val in varBinds: print(name.prettyPrint(),' ====== ',val.prettyPrint()) errorIndication, errorStatus, errorIndex, varBinds = next(g) for name,val in varBinds: print(name.prettyPrint(),' ====== ',val.prettyPrint()) 


Run, see the result:
<generator object nextCmd at 0x7f960364f8e0>
SNMPv2-SMI :: mib-2.4.20.1.1.10.239.192.2 ====== 10.239.192.2
SNMPv2-SMI :: mib-2.4.20.1.1.10.239.192.90 ====== 10.239.192.90
SNMPv2-SMI :: mib-2.4.20.1.1.11.0.0.1 ====== 11.0.0.1
SNMPv2-SMI :: mib-2.4.20.1.2.10.239.192.2 ====== 36
SNMPv2-SMI :: mib-2.4.20.1.2.10.239.192.90 ====== 1
The variable g is our generator. What does python tell us right away when it says print (g).
And then, using the next built-in function, the script enumerates the OID by the OID. Error values ​​are added to errorIndication, errorStatus, errorIndex, and the result is added to the varBinds list. To retrieve values ​​from varBinds, use the for loop:

 for name,val in varBinds: print(name.prettyPrint(),' ====== ',val.prettyPrint()) 

About generators in python many interesting articles are written, including on the habr, so I will not delve into this topic.

And now we have a very simple sequence of actions:

  1. We get addresses by OID 1.3.6.1.2.1.4.20.1.1, sorting out with the help of next, write the addresses into the list. For example, we will track the address 10.239.192.90.
  2. We get ifindex on OID 1.3.6.1.2.1.4.20.1.2, write to the list. For the address 10.239.192.90, the ifindex value of the interface is 1.
  3. indicating the value of ifindex. For the address 10.239.192.90, the final construction will be 1.3.6.1.2.1.31.1.1.1.18.1.
  4. We collect interface names using OID 1.3.6.1.2.1.31.1.1.1.1 + .ifindex.

It remains to collect the first two points into a function with snmpgetnext, and the remaining two points we collect using snmpget. The function will walk on the OID itself, sort through the values ​​in them and stop when all the OIDs have run out. OID will load the list. The list with OID is over - finish the work. The result will be returned in a two-dimensional list.

 def snmp_getnextcmd_next(community, ip, port, OID, file): #   class generator  def snmp_getnext # OID -   OID   list_OID = [OID_ipAdEntAddr,OID_ipAdEntIfIndex,OID_ipAdEntNetMask],     #   '1.2.3.4' #     ,   OID list_result = [] #      list_result2 = [] #   g = (snmp_getnextcmd(community, ip, port, OID[0])) #   OID varBinds = 0 flag = True for oid in list_OID: if varBinds != 0: for name, val in varBinds: list_result2.append(list_result) list_result = [] list_result.append(val.prettyPrint()) i = 0 while i <= 0: #   errorIndication, errorStatus, errorIndex, varBinds = next(g) if errors(errorIndication, errorStatus, errorIndex, ip_address_host, file): if str(varBinds).find(oid) != -1: i = 0 for name, val in varBinds: list_result.append(val.prettyPrint()) else: i = i + 1 flag = False else: file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'Error snmp_getnextcmd_next ip = ' + ip + ' OID = '+ OID[0] + '\n') print('Error snmp_getnextcmd_next ', False) i = i + 1 flag = False list_result2.append(list_result) return list_result2 

We receive the list containing ip of the address, ifindex, masks. The masks remained after the experiments, the heavy legacy of the past. To proceed to the next steps in collecting interface names, description, you need to filter the data. For example, Huawei equipment, Cisco will give addresses from the network 127.0.0.0/8, it makes no sense to form domain names for them. In the current version of the script, there is filtering on the allowed range of IPv4, everything that does not fall within the range is deleted. Obviously, for your networks, the filtering rules will be different.

We collect interface names, description using snmpget and proceed to the formation of zone files. To form a file of reverse zones, it is necessary to change the order of octets, for which you can use reverse_pointer from the ipaddress library or write something different.
print (ipaddress.ip_address ('194.4.5.1'). reverse_pointer)

1.5.4.194.in-addr.arpa
My script names the reverse zone files based on the addresses it receives from the router, it creates a dictionary in which the key consists of the first two octets of the ip-address. Then from these keys file names are formed. To do this, you still need to parse the address by octets. I attach a script that, having received the list of addresses of routers, should produce the correct zone files. He does this for me.

It seems that I told about all the necessary cubes to start working with equipment on snmp using python. Cubes can be combined as you like, but you can make your own.

Script example
 #       ,   . #      snmp sysname,     ,   ,   #   sysname  ,  , ifindex,  (  ,      )   #      -      traceback,    testresult   #   desc  name interface -   #  bind    check-names master ignore #      ,      .   - named.soa.    $INCLUDE #import section from pysnmp.hlapi import * from ipaddress import * from datetime import datetime import mysql.connector from mysql.connector import errorcode #    mysql   mysql.connector  python3 #     mysql,      .   -    ip          # var section #snmp community_string = 'community' # community string port_snmp = 161 OID_ipAdEntAddr = '1.3.6.1.2.1.4.20.1.1' # From SNMPv2-MIB ip  OID_ifNumber = '1.3.6.1.2.1.2.1.0' # From RFC1213-MIB   ifindex OID_sysName = '1.3.6.1.2.1.1.5.0' # From SNMPv2-MIB hostname/sysname OID_ipAdEntIfIndex = '1.3.6.1.2.1.4.20.1.2' # From SNMPv2-MIB ifindex interface OID_ipAdEntNetMask = '1.3.6.1.2.1.4.20.1.3' # From SNMPv2-MIB OID_ifAlias = '1.3.6.1.2.1.31.1.1.1.18' # Desc .    OID   ifindex OID_ifName = '1.3.6.1.2.1.31.1.1.1.1' #    OID   ifindex list_OID = [OID_ipAdEntAddr,OID_ipAdEntIfIndex,OID_ipAdEntNetMask] #log filename_log = 'zone_gen.log' #    log_level = 'debug' # ('normal'), ('debug'), ('min') # bind zone files file_direct_zone = 'spd.esrr.rzd.hosts' #     domain = 'domain.name.org' # domainname named_soa = '$INCLUDE /var/bind/named.soa' direct_zone =[] #     reverse_zone = {} #     name_server_record = 'dns.server.ru. IN A 10.111.33.21\n' ip_segment_ds = ['10.0.0.0/8'] #   ,     #var section for mysql username_db = 'username' #   mysql password_db = 'password' #   mysql db = 'name_database' #    query_from_db = 'select ip from devices where type = 2 or type = 3;' #  sql ; host = '192.11.33.123' #   # ip from file filename_of_ip = 'ip.txt' #    Ip  select_source_ip = 'file' #       ('file')  confstractor ('mysql') # function section def snmp_getnextcmd(community, ip, port, OID): # type class 'generator' errorIndication, errorStatus, errorIndex, result[3] #  next     ,      next() return (nextCmd(SnmpEngine(), CommunityData(community), UdpTransportTarget((ip, port)), ContextData(), ObjectType(ObjectIdentity(OID)))) def snmp_getcmd(community, ip, port, OID): # type class 'generator' errorIndication, errorStatus, errorIndex, result[3] -  #  get       SNMP   OID return (getCmd(SnmpEngine(), CommunityData(community), UdpTransportTarget((ip, port)), ContextData(), ObjectType(ObjectIdentity(OID)))) def snmp_get_next(community, ip, port, OID, file): #   class generator  def snmp_get #  errors,   class 'pysnmp.smi.rfc1902.ObjectType'  OID   #     errorIndication, errorStatus, errorIndex, varBinds = next(snmp_getcmd(community, ip, port, OID)) #     errors x = [] if errors(errorIndication, errorStatus, errorIndex, ip, file): for name, val in varBinds: return (val.prettyPrint(), True) else: file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : Error snmp_get_next ip = ' + ip + ' OID = ' + OID + '\n') return ('Error', False) def errors(errorIndication, errorStatus, errorIndex, ip, file): #      False     () if errorIndication: print(errorIndication, 'ip address ', ip) file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + str(errorIndication) + ' = ip address = ' + ip + '\n') return False elif errorStatus: print(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex) - 1][0] or '?')) file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '%s at %s' % (errorStatus.prettyPrint(), errorIndex and varBinds[int(errorIndex) - 1][0] or '?' + '\n')) return False else: return True def snmp_getnextcmd_next(community, ip, port, OID, file): #   class generator  def snmp_getnext # OID -   OID   list_OID = [OID_ipAdEntAddr,OID_ipAdEntIfIndex,OID_ipAdEntNetMask],     #   '1.2.3.4' #     ,   OID list_result = [] #      list_result2 = [] #   g = (snmp_getnextcmd(community, ip, port, OID[0])) #   OID varBinds = 0 flag = True for oid in list_OID: if varBinds != 0: for name, val in varBinds: list_result2.append(list_result) list_result = [] list_result.append(val.prettyPrint()) i = 0 while i <= 0: #   errorIndication, errorStatus, errorIndex, varBinds = next(g) if errors(errorIndication, errorStatus, errorIndex, ip_address_host, file): if str(varBinds).find(oid) != -1: i = 0 for name, val in varBinds: list_result.append(val.prettyPrint()) else: i = i + 1 flag = False else: file.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'Error snmp_getnextcmd_next ip = ' + ip + ' OID = '+ OID[0] + '\n') print('Error snmp_getnextcmd_next ', False) i = i + 1 flag = False list_result2.append(list_result) return list_result2 def check_ip(ip): #  ip  try: ip_address(ip) except ValueError: return False else: return True def check_ip2(ip): #  ip  try: ip_interface(ip) except ValueError: return False else: return True def get_from_mysql(host, user, password, db_name, query, fd): flag = True try: cnx = mysql.connector.connect(user=user, password = password, host = host ,database = db_name) if cnx.is_connected(): print('Connected to MySQL database') fd.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'Connected to MySQL database '+ host + '\n') cursor1 = cnx.cursor() cursor1.execute(query) query_result = [] i=0 list = [] for var in cursor1: query_result.append(str(var)[1:-2]) for var in query_result: # ,       ip     if var.isdigit(): if check_ip(int(var)): list.append(str(ip_address(int(var)))) # query_result.append(str(ip_address(int(str(var)[1:-2])))) except mysql.connector.Error as err: if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Something is wrong with your user name or password") fd.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + "Something is wrong with your user name or password" + '\n') flag = False elif err.errno == errorcode.ER_BAD_DB_ERROR: print("Database does not exist") fd.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + "Database does not exist" + '\n') flag = False else: print(err) fd(err) flag = False cursor1.close() cnx.close() return (list, flag) def get_from_file(file, filelog): #  ip   .   -      fd = open(file,'r') list_ip = [] for line in fd: line=line.rstrip('\n') if check_ip(line): list_ip.append(line) else: filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ': Error    ip  ' + line) fd.close() return list_ip # code section #   filed = open(filename_log,'w') #    filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + '\n') #     if select_source_ip == 'file': ip_from_confstractor = get_from_file(filename_of_ip, filed) else: if select_source_ip == 'mysql': ip_from_confstractor, flag_mysql = get_from_mysql(host , username_db, password_db, db, query_from_db, filed) if log_level == 'debug': filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'ip address from ' + select_source_ip + '\n') for var in ip_from_confstractor: filed.write(var + '\n') #    ifindex    #number_ifindex = (snmp_get_next(community_string, ip_address_host, port_snmp, OID_ifNumber)) for ip_address_host in ip_from_confstractor: #  sysname hostname+domainname,   sysname, flag_snmp_get = (snmp_get_next(community_string, ip_address_host, port_snmp, OID_sysName, filed)) if flag_snmp_get: #  ,    snmp if sysname == 'No Such Object currently exists at this OID' : #  community .  ,   traceback.     ,    community,     hostname,     print('ERROR community', sysname , ' ' , ip_address_host) filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'ERROR community sysname = ' + sysname + ' ip = ' + ip_address_host + '\n') else: if log_level == 'debug': filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + '  sysname ' + sysname + ' type ' + str(type(sysname)) + ' len ' + str(len(sysname)) + ' ip ' + ip_address_host + '\n') if len(sysname) < 3: sysname = 'None_sysname' if log_level == 'debug' or log_level == 'normal': filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'Error sysname  3  = ' + sysname + ' ip = ' + ip_address_host + '\n') if sysname.find(domain) == -1: # -  hostname  ,  Huawei  Catos sysname = sysname + '.' + domain # print("check domain    ", sysname, " ", ip_address_host , "\n") if log_level == 'debug' or log_level == 'normal': filed.write("check domain    : " + sysname + " " + ip_address_host + " " + "\n") else: #        pass # , ifindex,      # testresult[0] =  # testresult[1] = ifindex # testresult[2] =  testresult = snmp_getnextcmd_next(community_string, ip_address_host, port_snmp, list_OID, filed) i = 0 for var in testresult[0]: #      ip_segment_ds flag = 'False' for net in ip_segment_ds: if (IPv4Address(var) in IPv4Network(net)): flag = 'True' if flag == 'True': pass else: testresult[0].pop(i) testresult[1].pop(i) i = i +1 #  ifindex,  desc ,   ,       # testresult[3] = desc desc = [] i = 0 for var in testresult[1]: x, flag_snmp_get = snmp_get_next(community_string, ip_address_host, port_snmp, OID_ifAlias+'.'+var, filed) if flag_snmp_get: x = x.replace('"', '').replace(' ', '_').replace('(', '').replace(')', '').replace( ',', '.').replace(']','').replace('[','').replace("'","").replace('-_','').replace('_-','') desc.append(x) i = i + 1 else: i = i +1 testresult[1].pop(i) #       desc  ifindex,  ,   ifindex   #        .        . testresult[0].pop(i) #   ,        testresult.append(desc) #   #  ifindex,    desc = [] for var in testresult[1]: x, flag_snmp_get = snmp_get_next(community_string, ip_address_host, port_snmp, OID_ifName + '.' + var, filed) if flag_snmp_get: x = x.replace('Loopback', 'Lo').replace('loopback0', 'Lo0').replace(' ', '_') desc.append(x) i = i + 1 else: i = i + 1 testresult[1].pop(i) #          ifindex,  ,   ifindex   #        . testresult[0].pop(i) #   ,         tracebrake  testresult[3].pop(i) # desc ,         tracebrake  testresult.append(desc) #   #testresult[4]   i = 0 for var in testresult[3]: if var == 'No_Such_Object_currently_exists_at_this_OID': #  APC   Zyxel,   OID desc testresult[3][i] = '' testresult[4][i] = 'Lo0' i = i + 1 if log_level == 'debug': for var in testresult: filed.write(str(var) + '\n') #      i=0 for var in testresult[0]: rev = var.split('.') revs = rev[:] revs.reverse() revsstr='.'.join(revs) #     if (rev[0]+'.'+rev[1]) in reverse_zone: if testresult[4][i] == 'Lo0': reverse_zone[rev[0]+'.'+rev[1]].append(revsstr + '.in-addr.arpa. IN PTR ' + sysname + '.') else: reverse_zone[rev[0] + '.' + rev[1]].append(revsstr + '.in-addr.arpa. IN PTR ' + testresult[4][i] + '.' + testresult[3][i] + '.' + sysname + '.') else: reverse_zone[rev[0]+'.'+rev[1]] = [] if testresult[4][i] == 'Lo0': reverse_zone[rev[0] + '.' + rev[1]].append(revsstr + '.in-addr.arpa. IN PTR ' + sysname + '.') else: reverse_zone[rev[0] + '.' + rev[1]].append( revsstr + '.in-addr.arpa. IN PTR ' + testresult[4][i] + '.' + testresult[3][ i] + '.' + sysname + '.') #     if testresult[4][i] == 'Lo0': direct_zone.append(sysname + '.' + ' IN A ' + var) elif testresult[3][i] == '': direct_zone.append(testresult[4][i]+'.' + sysname + '.' +' IN A ' + var) else: direct_zone.append(testresult[4][i] + '.' + testresult[3][i] + '.' + sysname + '.' + ' IN A ' + var) i=i+1 else: print('Error      ip ', ip_address_host) filed.write(datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + ' : ' + 'Error      snmp, ip  ' + ip_address_host + ' ' + str(flag_snmp_get) + '\n') #      f=open(file_direct_zone, 'w') #    f.write(named_soa + '\n'+'\n') f.write(name_server_record) for i in direct_zone: i = i.replace('..','.') f.write(i + '\n') f.close() file_list_reverse = list(reverse_zone.keys()) print(file_list_reverse) if log_level == 'debug': for i in file_list_reverse: filed.write(i + '\n') for i in list(reverse_zone.keys()): #     f=open(i+'.rev','w') f.write(named_soa + '\n'+'\n') for y in reverse_zone[i]: y = y.replace('..', '.') f.write(y + '\n') f.close() #     filed.write('\n' + datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S") + '\n') #   filed.close() 


PS: Links



Debian wiki about SNMP
Nice article "SNMP MIBs and how to prepare them"


IReasoning MIB browser
In the free version, you can only work with 10 MIB at a time.
OpManager FREE MIB Browser


The script does not meet the requirements of the PEP8 Style Guide for Python Code , which is not very good.
If you want to collect logs from your scripts beautifully and correctly, logging - Logging facility for Python

Source: https://habr.com/ru/post/340050/


All Articles