Coding a simulator that spits out data at a defined rate can help simulate real load.
This recipe assumes that the reader's machine is installed with MySQL.
recipe63
as well as a user with permission to access it.With these steps, we will explore coding a test simulator:
recipe63.py
that uses various Python libraries.import getopt import random import sys import time from network import * from springpython.remoting.pyro import *
def usage(): print "Usage" print "=====" print "-h, --help read this help" print "-r, --rate [arg] number of events per second" print "-d, --demo demo by printing events"
getopt
library to parse command-line arguments.try: opts, args = getopt.getopt(sys.argv[1:], "hr:d", ["help", "rate=", "demo"]) except getopt.GetoptError, err: print str(err) usage() sys.exit(1) rate = 10 demo_mode = False for o, a in opts: if o in ("-h", "--help"): usage() sys.exit(1) elif o in ("-r", "--rate"): rate = a elif o in ("-d", "--demo"): demo_mode = True
PyroProxyFactory
to connect to a server instance of the network management application defined in Chapter 7, Building a network management application.if not demo_mode: print "Sending events to live network app. Ctrl+C to exit..." proxy = PyroProxyFactory() proxy.service_url = "PYROLOC://127.0.0.1:7766/network"
while True: hostname = random.choice(["pyhost1","pyhost2","pyhost3"]) condition = random.choice(["serverRestart", "lineStatus"]) severity = random.choice([1,5]) evt = Event(hostname, condition, severity)
if demo_mode: now = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime()) print "%s: Sending out %s" % (now, evt)
else: stored_event, is_active, updated_services, updated_equipment = proxy.process(evt) print "Stored event: %s" % stored_event print "Active? %s" % is_active print "Services updated: %s" % updated_services print "Equipment updated; %s" % updated_equipment print "================"
time.sleep(1.0/float(rate))
recipe63_server.py
that will run our network management app connected to MySQL using SQL script recipe62_network.sql
from Targeting the test server.from springpython.database.factory import * from springpython.database.core import * from springpython.remoting.pyro import * from network import * import logging logger = logging.getLogger("springpython") loggingLevel = logging.DEBUG logger.setLevel(loggingLevel) ch = logging.StreamHandler() ch.setLevel(loggingLevel) formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") ch.setFormatter(formatter) logger.addHandler(ch) # Initialize the database factory = MySQLConnectionFactory("user", "password", "localhost", "recipe63") dt = DatabaseTemplate(factory) sql = open("recipe62_network.mysql").read().split(";") for statement in sql: dt.execute(statement + ";")
# Create an instance of the network management app target_service = EventCorrelator(factory) # Expose the network app as a Pyro service exporter = PyroServiceExporter() exporter.service_name = "network" exporter.service = target_service exporter.after_properties_set()
Python's random.choice
method makes it easy to create a range of random events. By using the time.sleep
method, we can control the rate at which the events are created.
We used Pyro to connect the test generator to the network management application. This isn't the only way to connect things together. We could have exposed the application through other means, such as REST, JSON, or perhaps by communicating through a database table. That's not important. What is important is that we built an independent tool that fed data into our application as if it came from a live network.
We built a test generator. It's easy to run multiple copies of it in different shells, at different rates. We have an easy way to simulate different subnets producing different volumes of traffic.
We could also add more command-line options to fine tune the events. For example, we could make the event condition a parameter, and emulate different rates for different types of events.
A production version of the server wouldn't do this. For demonstration purposes of this recipe, it is convenient to put it there. Every time we stop and start the server script, it relaunches the database.
18.225.234.28