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 reactor 
 44  from Products.ZenUtils.Driver import drive 
 45  from Products.ZenUtils.Timeout import timeout 
 46  from Products.ZenEvents.ZenEventClasses import Error, Warning, Info, \ 
 47      Debug 
 48   
 49  from twisted.python import failure 
 50   
51 -class FakePacket(object):
52 """ 53 A fake object to make packet replaying feasible. 54 """
55 - def __init__(self):
56 self.fake = True
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 # Note what you are about to see below is a direct result of optparse 136 # adding in the arguments *TWICE* each time --replayFilePrefix is used. 137 import glob 138 files = [] 139 for filespec in self.options.replayFilePrefix: 140 files += glob.glob( filespec + '*' ) 141 142 self.loaded = 0 143 self.replayed = 0 144 from sets import Set 145 for file in Set(files): 146 self.log.debug( "Attempting to read packet data from '%s'" % file ) 147 try: 148 fp = open( file, "rb" ) 149 packet= cPickle.load(fp) 150 fp.close() 151 self.loaded += 1 152 153 except (IOError, EOFError): 154 fp.close() 155 self.log.exception( "Unable to load packet data from %s" % file ) 156 continue 157 158 self.log.debug("Calling application-specific replay() method") 159 self.replay(packet) 160 161 self.replayStop()
162 163
164 - def replay(self, packet):
165 """ 166 Replay a captured packet. This must be overridden. 167 168 @param packet: raw packet 169 @type packet: binary 170 """ 171 pass
172 173
174 - def replayStop(self):
175 """ 176 Twisted method that we use to override the default stop() method 177 for when we are replaying packets. This version waits to make 178 sure that all of our deferreds have exited before pulling the plug. 179 """ 180 self.log.debug( "Replayed %d of %d packets" % (self.replayed, self.loaded ) ) 181 if self.replayed == self.loaded: 182 self.log.info( "Loaded and replayed %d packets" % self.replayed ) 183 self.stop() 184 else: 185 reactor.callLater( 1, self.replayStop )
186 187
189 """ 190 This should be called explicitly in the base class' buildOptions 191 """ 192 self.parser.add_option('--captureFilePrefix', 193 dest='captureFilePrefix', 194 default=None, 195 help="Directory and filename to use as a template" + \ 196 " to store captured raw trap packets.") 197 self.parser.add_option('--captureAll', 198 dest='captureAll', 199 action='store_true', 200 default=False, 201 help="Capture all packets.") 202 self.parser.add_option('--captureIps', 203 dest='captureIps', 204 default='', 205 help="Comma-separated list of IP addresses to capture.") 206 self.parser.add_option('--replayFilePrefix', 207 dest='replayFilePrefix', 208 action='append', 209 default=[], 210 help="Filename prefix containing captured packet data. Can specify more than once.")
211