Package Products :: Package ZenUtils :: Module captureReplay
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenUtils.captureReplay

  1  #! /usr/bin/env python 
  2  ############################################################################## 
  3  #  
  4  # Copyright (C) Zenoss, Inc. 2009, all rights reserved. 
  5  #  
  6  # This content is made available according to terms specified in 
  7  # License.zenoss under the directory where your Zenoss product is installed. 
  8  #  
  9  ############################################################################## 
 10   
 11   
 12  __doc__ = """captureReplay 
 13      Common code to capture and replay packets. 
 14   
 15      To use: 
 16  1. Add the captureReplay mixin to the list of base classes 
 17   
 18  2. Add the following to the buildOptions method of the base class, after other 
 19     initialization: 
 20      captureReplay.buildOptions() 
 21   
 22  3. Add the following to the __init__ of the base class, before any other 
 23     option processing: 
 24     self.processCaptureReplayOptions() 
 25   
 26  4. Define a convertPacketToPython() method to convert a 'raw' packet into a 
 27     Python serializable object. 
 28   
 29  5. Add a call to the capturePacket() method to capture the packet. 
 30   
 31  6. Define a replay() method to replay the packet. 
 32  """ 
 33   
 34  import sys 
 35  import cPickle 
 36  from exceptions import EOFError, IOError 
 37  import glob 
 38   
 39  import Globals 
 40  from twisted.internet import defer, reactor 
 41  from Products.ZenUtils.Timeout import timeout 
 42  from Products.ZenEvents.ZenEventClasses import Error, Warning, Info, \ 
 43      Debug 
 44   
 45  from twisted.python import failure 
 46   
47 -class FakePacket(object):
48 """ 49 A fake object to make packet replaying feasible. 50 """
51 - def __init__(self):
52 self.fake = True
53 54
55 -class CaptureReplay(object):
56 """ 57 Base class for packet capture and replay capability. 58 Assumes that the other classes provide the following: 59 self.buildOptions() 60 self.sendEvent() 61 62 Overrides the self.connected() method if called to replay packets. 63 """ 64
66 """ 67 Inside of the initializing class, call these functions first. 68 """ 69 if self.options.captureFilePrefix and len(self.options.replayFilePrefix) > 0: 70 self.log.error( "Can't specify both --captureFilePrefix and -replayFilePrefix" \ 71 " at the same time. Exiting" ) 72 sys.exit(1) 73 74 if self.options.captureFilePrefix and not self.options.captureAll and \ 75 self.options.captureIps == '': 76 self.log.warn( "Must specify either --captureIps or --captureAll for" + \ 77 " --capturePrefix to take effect. Ignoring option --capturePrefix" ) 78 79 if len(self.options.replayFilePrefix) > 0: 80 self.connected = self.replayAll 81 return 82 83 self.captureSerialNum = 0 84 self.captureIps = self.options.captureIps.split(',')
85
86 - def convertPacketToPython(*packetInfo):
87 """ 88 Convert arguments into an plain object (no functions) suitable 89 for pickling. 90 """ 91 pass
92
93 - def capturePacket(self, hostname, *packetInfo):
94 """ 95 Store the raw packet for later examination and troubleshooting. 96 97 @param hostname: packet-sending host's name or IP address 98 @type hostname: string 99 @param packetInfo: raw packet and other necessary arguments 100 @type packetInfo: args 101 """ 102 # Save the raw data if requested to do so 103 if not self.options.captureFilePrefix: 104 return 105 if not self.options.captureAll and hostname not in self.captureIps: 106 self.log.debug( "Received packet from %s, but not in %s" % (hostname, 107 self.captureIps)) 108 return 109 110 self.log.debug( "Capturing packet from %s" % hostname ) 111 name = "%s-%s-%d" % (self.options.captureFilePrefix, hostname, self.captureSerialNum) 112 try: 113 packet = self.convertPacketToPython(*packetInfo) 114 capFile = open( name, "wb") 115 data= cPickle.dumps(packet, cPickle.HIGHEST_PROTOCOL) 116 capFile.write(data) 117 capFile.close() 118 self.captureSerialNum += 1 119 except: 120 self.log.exception("Couldn't write capture data to '%s'" % name )
121
122 - def replayAll(self):
123 """ 124 Replay all captured packets using the files specified in 125 the --replayFilePrefix option and then exit. 126 127 Note that this calls the Twisted stop() method 128 """ 129 if hasattr(self, 'configure'): 130 d = self.configure() 131 d.addCallback(self._replayAll) 132 else: 133 self._replayAll()
134
135 - def _replayAll(self, ignored):
136 # Note what you are about to see below is a direct result of optparse 137 # adding in the arguments *TWICE* each time --replayFilePrefix is used. 138 files = [] 139 for filespec in self.options.replayFilePrefix: 140 files += glob.glob( filespec + '*' ) 141 142 self.loaded = 0 143 self.replayed = 0 144 for file in set(files): 145 self.log.debug( "Attempting to read packet data from '%s'" % file ) 146 try: 147 fp = open( file, "rb" ) 148 packet= cPickle.load(fp) 149 fp.close() 150 self.loaded += 1 151 152 except (IOError, EOFError): 153 fp.close() 154 self.log.exception( "Unable to load packet data from %s" % file ) 155 continue 156 157 self.log.debug("Calling application-specific replay() method") 158 self.replay(packet) 159 160 self.replayStop()
161
162 - def replay(self, packet):
163 """ 164 Replay a captured packet. This must be overridden. 165 166 @param packet: raw packet 167 @type packet: binary 168 """ 169 pass
170
171 - def replayStop(self):
172 """ 173 Twisted method that we use to override the default stop() method 174 for when we are replaying packets. This version waits to make 175 sure that all of our deferreds have exited before pulling the plug. 176 """ 177 if self.replayed == self.loaded: 178 self.log.info("Loaded and replayed %d packets" % self.replayed) 179 reactor.stop() 180 else: 181 reactor.callLater(1, self.replayStop)
182
183 - def buildCaptureReplayOptions(self, parser):
184 """ 185 This should be called explicitly in the base class' buildOptions 186 """ 187 parser.add_option('--captureFilePrefix', 188 dest='captureFilePrefix', 189 default=None, 190 help="Directory and filename to use as a template" + \ 191 " to store captured raw trap packets.") 192 parser.add_option('--captureAll', 193 dest='captureAll', 194 action='store_true', 195 default=False, 196 help="Capture all packets.") 197 parser.add_option('--captureIps', 198 dest='captureIps', 199 default='', 200 help="Comma-separated list of IP addresses to capture.") 201 parser.add_option('--replayFilePrefix', 202 dest='replayFilePrefix', 203 action='append', 204 default=[], 205 help="Filename prefix containing captured packet data. Can specify more than once.")
206