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

Source Code for Module Products.ZenUtils.captureReplay

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