1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#!/usr/bin/env python
# -------------------------------------------------------------------------- #
# System
# -------------------------------------------------------------------------- #
import os
import getpass
import pickle
from threading import Thread
# -------------------------------------------------------------------------- #
# SNMP Simulator
# -------------------------------------------------------------------------- #
from twisted.internet import reactor
from twisted.internet import error as twisted_error
from pymodbus.server.asynchronous import ModbusServerFactory
from pymodbus.datastore import ModbusServerContext,ModbusSlaveContext
# -------------------------------------------------------------------------- #
# Logging
# -------------------------------------------------------------------------- #
import logging
log = logging.getLogger("pymodbus")
# -------------------------------------------------------------------------- #
# Application Error
# -------------------------------------------------------------------------- #
class ConfigurationException(Exception):
""" Exception for configuration error """
pass
# -------------------------------------------------------------------------- #
# Extra Global Functions
# -------------------------------------------------------------------------- #
# These are extra helper functions that don't belong in a class
# -------------------------------------------------------------------------- #
def root_test():
""" Simple test to see if we are running as root """
return getpass.getuser() == "root"
# -------------------------------------------------------------------------- #
# Simulator Class
# -------------------------------------------------------------------------- #
class Simulator(object):
"""
Class used to parse configuration file and create and modbus
datastore.
The format of the configuration file is actually just a
python pickle, which is a compressed memory dump from
the scraper.
"""
def __init__(self, config):
"""
Trys to load a configuration file, lets the file not
found exception fall through
:param config: The pickled datastore
"""
try:
self.file = open(config, "r")
except Exception:
raise ConfigurationException("File not found %s" % config)
def _parse(self):
""" Parses the config file and creates a server context """
try:
handle = pickle.load(self.file)
dsd = handle['di']
csd = handle['ci']
hsd = handle['hr']
isd = handle['ir']
except KeyError:
raise ConfigurationException("Invalid Configuration")
slave = ModbusSlaveContext(d=dsd, c=csd, h=hsd, i=isd)
return ModbusServerContext(slaves=slave)
def _simulator(self):
""" Starts the snmp simulator """
ports = [502]+range(20000,25000)
for port in ports:
try:
reactor.listenTCP(port, ModbusServerFactory(self._parse()))
log.debug('listening on port %d' % port)
return port
except twisted_error.CannotListenError:
pass
def run(self):
""" Used to run the simulator """
log.debug('simulator started')
reactor.callWhenRunning(self._simulator)
# -------------------------------------------------------------------------- #
# Network reset thread
# -------------------------------------------------------------------------- #
# This is linux only, maybe I should make a base class that can be filled
# in for linux(debian/redhat)/windows/nix
# -------------------------------------------------------------------------- #
class NetworkReset(Thread):
"""
This class is simply a daemon that is spun off at the end of the
program to call the network restart function (an easy way to
remove all the virtual interfaces)
"""
def __init__(self):
""" Initialize a new network reset thread """
Thread.__init__(self)
self.setDaemon(True)
def run(self):
""" Run the network reset """
os.system("/etc/init.d/networking restart")
|