import types
import string
import socket
import asyncore
import asynchat
# Import asynchronous wrap over PySNMP module
from pysnmp import asynsnmp
class telnet_engine (asynchat.async_chat):
"""Telnet engine class. Implements command line user interface.
"""
def __init__ (self, sock):
# Call constructor of the parent class
asynchat.async_chat.__init__ (self, sock)
# Set up input line terminator
self.set_terminator ('\n')
# Initialize input data buffer
self.data = ''
# User interface goodies
self.prompt = 'query> '
self.welcome = 'Example Telnet server / SNMP manager ready.\n'
self.help = 'Syntax: \n'
# Send welcome message down to user. By using push() method we
# having asynchronous engine delivering welcome message to user.
self.push (self.welcome + self.help + self.prompt)
def collect_incoming_data (self, data):
"""Put data read from socket to a buffer
"""
# Collect data in input buffer
self.data = self.data + data
def found_terminator (self):
"""This method is called by asynchronous engine when it finds
command terminator in the input stream
"""
# Take the complete line
line = self.data
# Reset input buffer
self.data = ''
# Handle user command
response = self.process_command (line)
# Let's see if there is anything to reply to user
if response:
# Deliver message back to user
self.push (response + '\n' + self.prompt)
def request_done_fun (self, manager, context,\
encoded_objids, encoded_values):
"""Callback method invoked by SNMP manager object as request
completes. Asynchronous SNMP manager object passes back a
reference to object instance that initiated this SNMP request
along with lists of BER encoded Object IDs and associated
values as received from SNMP agent.
"""
# Close SNMP session
manager.close ()
# Initialize response buffer
response = 'Response from agent %s:\n' % manager.agent
# See if there is a response from remote SNMP agent
if encoded_objids is None or encoded_values is None:
response = response + 'Remote SNMP agent reported an error (possibly bad Object ID)\n'
else:
# Decode BER encoded Object ID.
objids = map (manager.decode_value, encoded_objids)
# Decode BER encoded values associated with Object IDs.
values = map (manager.decode_value, encoded_values)
# Convert two lists into a list of tuples for easier printing
results = map (None, objids, values)
# Just print them out
for (objid, value) in results:
response = response + objid + ' ---> ' + str(value) + '\n'
# Send reply back to user
self.push (response + self.prompt)
def process_command (self, line):
"""Process user input
"""
# Make sure request is not empty
if not line:
# Just do nothing
return ''
# Split request up to fields
args = string.split (line)
# Make sure we got enough arguments
if len (args) < 3:
return 'Insufficient number of arguments'
# Create new asynchronous SNMP manager object and pass
# user supplied arguments along with callback method and
# a reference to an instance of calling class.
manager = asynsnmp.async_session (args[0], args[1], \
self.request_done_fun,\
self)
# Convert string type Object IDs into numeric representation
numeric_objids = map (manager.str2nums, args[2:])
# BER encode SNMP Object IDs to query
encoded_objids = map (manager.encode_oid, numeric_objids)
# Since we are going to _query_ SNMP agent for Object ID
# associated value, there will be no Object ID value passed to SNMP
# agent.
encoded_values = []
# Open SNMP session
manager.open ()
# Build and send SNMP message of type 'GETREQUEST', pass it a list
# of BER encoded Object IDs to query (only one in this case) and
# an empty list of associated values for these Object IDs (empty
# list as there is no point to pass any values along the SNMP GET
# request)
manager.send_request (encoded_objids, encoded_values)
# Expect a reply from SNMP agent later
return None
class telnet_server (asyncore.dispatcher):
"""Telnet server class. Listens for incoming requests and creates
instances of telnet engine classes for handling new session.
"""
def __init__ (self, port=8989):
"""Takes optional TCP port number for the server to bind to.
"""
# Call parent class constructor explicitly
asyncore.dispatcher.__init__ (self)
# Create socket of requested type
self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
# Set it to re-use address
self.set_reuse_addr ()
# Bind to all interfaces of this host at specified port
self.bind (('', port))
# Start listening for incoming requests
self.listen (5)
def handle_accept (self):
"""Called by asyncore engine when new connection arrives
"""
# Accept new connection
(sock, addr) = self.accept ()
# Create an instance of Telnet engine class to handle this new user
# session and pass it socket object to use any further
telnet_engine (sock)
# Run the module if it's invoked for execution
if __name__ == '__main__':
# Create an instance of Telnet server
server = telnet_server ()
# Start the select() I/O multiplexing loop
asyncore.loop()
Need help? Try PySNMP mailing lists.
|